2014-09-21 80 views
2

在LDD3書中,它介紹了簡單的睡眠(wait_event *()函數)和提前睡眠(prepare_to_wait()函數)。簡單睡眠(使用wait_event _ *()函數)和高級睡眠(使用prepare_to_wait()函數)有什麼區別?

如果我的理解是正確的,wait_queue_t似乎是一個過程條目,但wait_queue_head_t似乎是等待隊列中存儲的哪個(wait_queue_t)被添加的進程列表中..

所以,說到我的混淆了什麼情況下,我應該使用wait_event _ *()函數與prepare_to_wait並指定等待進程。

我可以說的唯一原因是我可以在睡覺前指定過程狀態而不是簡單的睡眠。但是,簡單的睡眠確實提供了可中斷和不可中斷的wait_event功能。所以,我有點困惑,爲什麼我們需要從設計和實現的角度來看兩者。謝謝。

回答

5

這是wait_event()簡化)實施:

#define wait_event(wq, condition) 
{ 
    DEFINE_WAIT(wait); 
    for (;;) { 
     prepare_to_wait(&wq, &wait, TASK_UNINTERRUPTIBLE); 
     if (condition) 
      break; 
     schedule(); 
    } 
    finish_wait(&wq, &wait); 
} 

如果此實現(或其他許多wait_event_*變種之一)爲你工作,那麼你應該使用它。

但是,可能有些情況下需要對此等待循環進行更多的控制。 例如,假設您想等待某些數據在緩衝區中可用並返回,並且這兩個操作都需要在鎖定下完成,並且檢查數據刪除數據需求是一個原子操作,也就是說,兩者必須在相同的鎖定下完成,而不需要解鎖。 然後,你將不得不像上面這樣修改上面的循環:

void my_own_wait(...) 
{ 
    DEFINE_WAIT(wait); 
    spin_lock(&lock); 
    while (!some_data_available()) { 
     prepare_to_wait(&wq, &wait, TASK_xxx); 
     spin_unlock(&lock); 
     schedule(); 
     spin_lock(&lock); 
     finish_wait(&wq, &wait); 
    } 
    take_data(); 
    spin_unlock(&lock); 
} 
+0

嗨,CL。感謝您的迴應。然而,我看起來像我仍然可以使用wait_event將它放在my_own_wait實現...唯一的區別是,我可以把條件放在while循環中而不是在wait_event()中使用condition參數... – rickhau 2014-09-23 03:04:26

+0

在現實世界中,事情往往比'my_own_wait'更復雜;這同樣適用於'wait_event'(它多次使用'condition')。但是,如果你的代碼*不能正確的使用'wait_event',那麼一定要用它。 – 2014-09-23 06:49:09

+0

根據ldd3,除非將'schedule()'包裝在'if(!some_data_available())'中,否則會有一場競賽。 (在有些數據可用的情況下,有人試圖喚醒我們,在while檢查之後和prepare_to_wait()之前)http://www.makelinux.net/ldd3/chp-6-sect-2 – ted 2017-04-13 13:23:15