來自: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。
從而可以在下次調度時運行。
喚醒是別人的動作。