2013-10-12 68 views
3

我「由羅伯特·愛的Linux內核開發第3版」,以獲取有關Linux內核是如何工作的總體思路閱讀。(2.6.2.3)Linux內核 - 等待隊列

我感到困惑如何等待隊列例如工作驗證碼:

/* ‘q’ is the wait queue we wish to sleep on */ 
DEFINE_WAIT(wait); 
add_wait_queue(q, &wait); 

while (!condition) { /* condition is the event that we are waiting for */ 
    prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE); 
    if (signal_pending(current)) 
     /* handle signal */ 
     schedule(); 
    } 

finish_wait(&q, &wait); 
  • 我想知道哪些進程正在運行該代碼?它是一個內核線程?其處理時間是這樣的?

  • 以及在循環,而病情依然沒有得到滿足,我們將繼續睡覺,並呼籲時間表運行另一個程序問題是當我們回到這個循環?

  • 書中說,當一個進程睡眠,它是從我們的運行隊列中刪除,否則會被喚醒,並已經進入一個繁忙的循環......

  • 還說:「睡覺應始終處理一個確保任務等待的條件確實已經發生的循環。「

我只是想在這篇循環運行的情況下知道的嗎?

對不起,如果這是一個愚蠢的問題。我只是無法看到的大圖

回答

6

哪些進程正在運行的代碼?調用它的過程。我並不是想嘲笑這個問題,但要點是內核代碼可以在不同的上下文中運行:因爲系統調用導致了這個地方,因爲它在中斷處理程序中,或者因爲它是一個稱爲回調函數來自另一個上下文(例如工作隊列或計時器功能)。

由於本例是睡覺,它必須是在睡眠允許一個方面,它是響應於一個系統呼叫或至少在一個內核線程執行的意思。所以答案是從進程(或內核線程)獲取進程時間,該進程需要進入需要休眠的內核代碼。那是唯一允許睡覺的地方。

某種特殊情況下是工作隊列,這些都是明確爲需要睡眠功能。典型的用法是將一個需要睡眠的函數從禁止睡眠的上下文中排隊。在這種情況下,進程上下文是指定用於處理工作隊列項目的內核工作線程之一。

當wait_queue被喚醒,這既可以設定一個任務在等待隊列中可運行或全部,這取決於稱爲WAKE_UP功能,您將返回到這個循環。

最重要的是,忘掉這一點,除非你有興趣的實施細則。由於許多人得到了這個錯誤,而且在任何需要的地方都是基本相同的東西,因此長期以來一直封裝整個過程的宏。查找wait_event函數(),這是怎麼你的榜樣應該真正的樣子:

wait_event(q, condition); 
+0

歡迎來到SO!偉大的第一個答案 –

+0

謝謝,@BrianCain! –

+1

這不是調度程序的一部分(您可以看到它是_calling_ schedule()),它正在將自己置於睡眠狀態。這是一個標準的代碼,等待一個wait_queue,直到滿足一個條件,這樣它的標準被封裝在wait_event()中。這比內核搶佔要早。 –

1

按你的榜樣......我添加了註釋....

注:創建默認等待隊列會處於睡眠狀態。

DEFINE_WAIT(wait);/*首先等待--->它將它指向的內核全局等待隊列*/

add_wait_queue(q,& wait);/*首先等待--->它使用add_wait_queue指向的內核全局等待隊列(q,& wait); --->你正在添加自己的等待隊列(如追加鏈表)*/

while(!condition){0}條件是我們正在等待的事件*/ /*條件 - >比方說,你在(使用__get_user())*/

prepare_to_wait(&q, &wait, TASK_INTERRUPTIBLE); 

/*這將等待時將其中斷*/ 如果(signal_pending產生的任何wake_up_process()調用獲取的寫入方法從用戶空間數據(電流))

/*這將持續監視當前CPU是否有任何信號掛起在不等待任何通常使用的信號的情況下運行等待隊列返回-ERESTARTSYS;或 「破發」 的循環,如果中斷來到EXA,SIGINT或者SIGKILL和完成等待隊列語句來再次檢查/ /手柄信號*/

schedule(); // Scheduling of wait queue 
       // Remove from global data structure 
} 

finish_wait(& Q,&等待)。 //完成排隊