您的位置:首页 > 其它

wake_up_interruptible 函数

2013-12-18 09:49 495 查看
功能:唤醒注册到等待队列上的进程

原型

    #include
    void wake_up_interruptible (wait_queue_head_t *q);

说明

    唤醒 q 指定的注册在等待队列上的进程。该函数不能直接的立即唤醒进程,而是由调度程序转换上下文,调整为可运行状态。

变量

q :  等待队列变量指针。

 

    最近在学习驱动时有一个问题始终想不明白,为什么wait_event_interruptible(button_waitq, ev_press)需要一个全局变量来记住中断的发生?

在驱动中实现读取操作时,使用了

wait_event_interruptible(button_waitq, ev_press);

在中断函数中使用了如下语句唤醒:

ev_press = 1;  //表示中断发生了

wake_up_interruptible(&button_waitq);  //唤醒休眠的进程

这样的话,中断能正确读取到。我分别尝试了屏蔽ev_press = 1;和wake_up_interruptible(&button_waitq);代码,发现中断不能正常产生。

查找资料,阅读源代码。

#define wait_event_interruptible(wq, condition)          \

({                                                       \

    int __ret = 0;                                       \

    if (!(condition))                                    \

        __wait_event_interruptible(wq, condition, __ret);\

    __ret;                                               \

})

#define __wait_event_interruptible(wq, condition, ret)                        \

do {                                                                        \

        DEFINE_WAIT(__wait);                                                \

                                                                        \

        for (;;) {                                                        \

                prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);        \

                if (condition)                                                \

                        break;                                                \

                if (!signal_pending(current)) {                                \

                        schedule();                                        \

                        continue;                                        \

                }                                                        \

                ret = -ERESTARTSYS;                                        \

                break;                                                        \

        }                                                                \

        finish_wait(&wq, &__wait);                                        \

} while (0)

__wait_event_interruptible()首先定义并初始化一个wait_queue_t变量__wait,其中数据为当前进程current,并把__wait入队。
    在无限循环中,__wait_event_interruptible()将本进程置为可中断的挂起状态,反复检查condition是否成立,如果成立则退出,如果不成立则继续休眠;条件满足后,即把本进程运行状态置为运行态(此时如果不执行下面的函数 wake_up_interruptible,上面wait_event_interruptible还会继续休眠),并将__wait从等待队列中清除掉,从而进程能够调度运行。如果进程当前有异步信号(POSIX的),则返回-ERESTARTSYS。

//唤醒 q 指定的注册在等待队列上的进程。该函数不能直接的立即唤醒进程,而是由调度程序转换上下文,调整为可运行状态。

wake_up_interruptible (wait_queue_head_t *q);

我是这样考虑的:read 调用wait_event_interruptible(button_waitq),我觉得一个参数就够了。不判断什么条件,直接休眠,下面用wake_up_interruptible(&button_waitq)直接唤醒。这样看起来很简单。
不知道内核这样设计是基于什么原因?
上下文切换(Context
Switching):在多任务系统中,上下文切换是指CPU的控制权由运行任务转移到另外一个就绪任务时所发生的事件,当前运行任务转为就绪(或者挂起、删除)状态,另一个被选定的就绪任务成为当前任务。上下文切换包括保存当前任务的运行环境,恢复将要运行任务的运行环境。上下文的内容依赖于具体的CPU。

 
http://www.groad.net/bbs/read.php?tid-1336.html
http://www.100ask.net/forum/showtopic-4322.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: