_wait_event 具体实现过程

_wait_event 具体实现过程

分类: 网络文摘 87人阅读 评论(1) 收藏 举报

来自:http://www.linuxforum.net/forum/showthreaded.php?Board=linuxK&Number=572220

是不是当前进程要等待某个condition,然后就把它加到这个等待这个condition的wq中 
_wait_event是当前进程调用它,也就是在宏DEFINE_WAIT(_wait)中的_wait就是把当前进程设置成_wait加到等待队列里, 


以上基本正确 


如果condition发生,是这个进程被唤醒设置成running而不是整个等待队列wq被唤醒? 
如果conditon没有发生,还在prepare_to_wait里,这里保证了_wait不会被第二次加到等待队列中,但是第一次循环是加入了。finish_wait是将_wait移除。 
那么在DEFINE_WAIT中的func设置成autoremove_wake_function意义何在? 


prepare_to_wait()和finish_wait()并不是进程睡眠的地方,进程睡眠的地方是schedule(). 
prepare_to_wait()只是进行一些链表的操作,以确保自己在等待队列中,不会漏掉事件。 
进程在确信自己已经在队列中后,再次检查条件, 
这里,如果不检查,可能条件已经满足,直接去睡眠的话,可能再也没有人来唤醒它了。 

然后,如果条件不满足,就调用schedule()去睡眠, 
这里,进程的状态在prepare_to_wait()里设置为TASK_UNINTERRUPTIBLE, 
所以,以后调度时就看不到该进程了,因此,该进程将没有机会运行,这就是睡眠。 

注意,这里,该进程自己已经无能为力了,因为它自己已经不可能运行了。 
只有等待他人来唤醒了。 

当条件满足后,会有一个人(或者是其他进程,或者内核本身,等等)来唤醒某个等待队列上的进程。 
具体是唤醒全部等待队列中的所有进程,还是只唤醒第一个进程,完全取决于该唤醒者, 
等待在队列中的睡眠进程是无能为力的,与它们是没有关系的(呵呵,确切说,有一点关系)。 

唤醒者通常调用__wake_up_common(),这样,依次取下等待队列中的__wait_queue_t结构, 
调用该睡眠进程设置的func函数,即这里的autoremove_wake_function(), 
将该进程的状态重新设置为RUNNING, 
注意,此时该睡眠进程并不会立刻执行,只有等到下次调度的时候,该进程才有机会运行, 
即醒来了。醒来是从schedule()回来,继续运行__wait_event() 


总结一下, 
睡眠是自己设置好进程状态(TASK_UNINTERRUPTIBLE,等等),加入等待队列, 
并调用schedule()去睡眠。 

睡眠是自己的动作。 

唤醒是别人发现条件满足,调用__wake_up_common(),将睡眠进程从等待队列取下, 
调用该睡眠进程设置的唤醒func,重新设置该睡眠进程为RUNNING。 
从而可以在下次调度时运行。 

唤醒是别人的动作。 

原文地址:https://www.cnblogs.com/yuzaipiaofei/p/4124197.html