wait event 具體實現過程

2021-06-28 10:39:30 字數 1572 閱讀 7562

#define __wait_event(wq, condition) 

do  

finish_wait(&wq, &__wait); 

} while (0)

在define_wait(__wait)中

#define define_wait(name) 

wait_queue_t name = , 

} 的autoremove_wake_function:

int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key) 

prepare_to_wait()和finish_wait()並不是程序睡眠的地方,程序睡眠的地方是schedule()。

prepare_to_wait()只是進行一些鍊錶的操作,以確保自己在等待佇列中,不會漏掉事件。

程序在確信自己已經在佇列中後,再次檢查條件, 這裡,如果不檢查,可能條件已經滿足,直接去睡眠的話,可能再也沒有人來喚醒它了。

然後,如果條件不滿足,就呼叫schedule()去睡眠,這裡,程序的狀態在prepare_to_wait()裡設定為task_uninterruptible, 所以,以後排程時就看不到該程序了,因此,該程序將沒有機會執行,這就是睡眠。

注意,這裡,該程序自己已經無能為力了,因為它自己已經不可能執行了。 只有等待他人來喚醒了。

當條件滿足後,會有乙個人(或者是其他程序,或者核心本身,等等)來喚醒某個等待佇列上的程序。

具體是喚醒全部等待佇列中的所有程序,還是只喚醒第乙個程序,完全取決於該喚醒者, 等待在佇列中的睡眠程序是無能為力的,與它們是沒有關係的(呵呵,確切說,有一點關係)。

總是喚醒所有等待該事件的程序並不一定是合適的。比如考慮這樣一種情況:如果佇列中的多個程序等待的資源是要互斥訪問的,一定時間內只允許乙個程序去訪問的話,這時候,只需要喚醒乙個程序就可以了,其他程序繼續睡眠。如果喚醒所有的程序,最終也只有乙個程序獲得該資源,其他程序讓需返回睡眠。

因此,等待佇列中的睡眠程序可被劃分為互斥、非互斥程序。

互斥程序:等待的資源是互斥訪問的;互斥程序由核心有選擇的喚醒,等待佇列項的flag欄位為1;

非互斥程序:等待的資源是可多程序同時訪問的。非互斥程序在事件發生時,總是被核心喚醒,等待佇列元素的flag欄位為0。

喚醒者通常呼叫__wake_up_common(),這樣,依次取下等待佇列中的__wait_queue_t結構, 呼叫該睡眠程序設定的func函式,即這裡的autoremove_wake_function(), 將該程序的狀態重新設定為running。

注意,此時該睡眠程序並不會立刻執行,只有等到下次排程的時候,該程序才有機會執行, 即醒來了。醒來是從schedule()回來,繼續執行__wait_event()

總結一下, 睡眠是自己設定好程序狀態(task_uninterruptible,等等),加入等待佇列, 並呼叫schedule()去睡眠。 睡眠是自己的動作。

喚醒是別人發現條件滿足,呼叫__wake_up_common(),將睡眠程序從等待佇列取下, 呼叫該睡眠程序設定的喚醒func,重新設定該睡眠程序為running。 從而可以在下次排程時執行。 喚醒是別人的動作。

struts的具體執行過程

struts有乙個 控制器actionservlet,負責處理使用者的url請求,actionservlet在web.xml檔案中配置,它繼承了httpservlet,其實就是乙個普通的servlet。actionservlet中有兩個方法,如下 process方法繼續呼叫requestproces...

KM演算法及其具體過程

km演算法及其具體過程 1 可行點標 每個點有乙個標號,記lx i 為x方點i的標號,ly j 為y方點j的標號。如果對於圖中的任意邊 i,j,w 都有lx i ly j w,則這一組點標是可行的。特別地,對於lx i ly j w的邊 i,j,w 稱為可行邊 2 km 演算法的核心思想就是通過修改...

scp v 檢視具體的過程

前幾天跟同事討論scp 多個檔案和 scp多個資料夾的壓縮包那個快。老大說,壓縮包快,壓縮包傳輸可以避免每個檔案的重建連線,不過檔案系統的遍歷 目錄建立 檢驗會有一些開銷。他建議我scp v看下具體傳輸的過程。第一次聽說還有 v這個引數,試驗如下 cbcq git master scp v test...