_wait_event 具體實現(xiàn)過程
時間:2017-01-06作者:華清遠(yuǎn)見
#define __wait_event(wq, condition)
for (;;) {
在DEFINE_WAIT(__wait)中
int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
if (ret) prepare_to_wait()和finish_wait()并不是進(jìn)程睡眠的地方,進(jìn)程睡眠的地方是schedule()。 prepare_to_wait()只是進(jìn)行一些鏈表的操作,以確保自己在等待隊列中,不會漏掉事件。 進(jìn)程在確信自己已經(jīng)在隊列中后,再次檢查條件, 這里,如果不檢查,可能條件已經(jīng)滿足,直接去睡眠的話,可能再也沒有人來喚醒它了。 然后,如果條件不滿足,就調(diào)用schedule()去睡眠,這里,進(jìn)程的狀態(tài)在prepare_to_wait()里設(shè)置為TASK_UNINTERRUPTIBLE, 所以,以后調(diào)度時就看不到該進(jìn)程了,因此,該進(jìn)程將沒有機(jī)會運行,這就是睡眠。 注意,這里,該進(jìn)程自己已經(jīng)無能為力了,因為它自己已經(jīng)不可能運行了。 只有等待他人來喚醒了。 當(dāng)條件滿足后,會有一個人(或者是其他進(jìn)程,或者內(nèi)核本身,等等)來喚醒某個等待隊列上的進(jìn)程。 具體是喚醒全部等待隊列中的所有進(jìn)程,還是只喚醒第一個進(jìn)程,完全取決于該喚醒者, 等待在隊列中的睡眠進(jìn)程是無能為力的,與它們是沒有關(guān)系的(呵呵,確切說,有一點關(guān)系)。 總是喚醒所有等待該事件的進(jìn)程并不一定是合適的。比如考慮這樣一種情況:如果隊列中的多個進(jìn)程等待的資源是要互斥訪問的,一定時間內(nèi)只允許一個進(jìn)程去訪問的話,這時候,只需要喚醒一個進(jìn)程就可以了,其他進(jìn)程繼續(xù)睡眠。如果喚醒所有的進(jìn)程,終也只有一個進(jìn)程獲得該資源,其他進(jìn)程讓需返回睡眠。 因此,等待隊列中的睡眠進(jìn)程可被劃分為互斥、非互斥進(jìn)程。
互斥進(jìn)程:等待的資源是互斥訪問的;互斥進(jìn)程由內(nèi)核有選擇的喚醒,等待隊列項的flag字段為1; 喚醒者通常調(diào)用__wake_up_common(),這樣,依次取下等待隊列中的__wait_queue_t結(jié)構(gòu), 調(diào)用該睡眠進(jìn)程設(shè)置的func函數(shù),即這里的autoremove_wake_function(), 將該進(jìn)程的狀態(tài)重新設(shè)置為RUNNING。 注意,此時該睡眠進(jìn)程并不會立刻執(zhí)行,只有等到下次調(diào)度的時候,該進(jìn)程才有機(jī)會運行, 即醒來了。醒來是從schedule()回來,繼續(xù)運行__wait_event() 總結(jié)一下, 睡眠是自己設(shè)置好進(jìn)程狀態(tài)(TASK_UNINTERRUPTIBLE,等等),加入等待隊列, 并調(diào)用schedule()去睡眠。 睡眠是自己的動作。 喚醒是別人發(fā)現(xiàn)條件滿足,調(diào)用__wake_up_common(),將睡眠進(jìn)程從等待隊列取下, 調(diào)用該睡眠進(jìn)程設(shè)置的喚醒func,重新設(shè)置該睡眠進(jìn)程為RUNNING。 從而可以在下次調(diào)度時運行。 喚醒是別人的動作。
相關(guān)資訊
發(fā)表評論
|