網上有關於此函數的分析,但大都是同一篇文章轉載來轉載去,沒有進一步的分析。做個小結:
瞭解函數功能,除了直接看代碼邏輯,最有效的當是註釋內容了。
如下:
函數原型:wait_event_interruptible_timeout(wq, condition, timeout)
* 函數作用:~睡眠~,直到condition爲真,或timeout超時;
* @wq: 要等待的等待隊列
* @condition: 等待事件發生的條件(一個C表達式 )
* @timeout: 超時時間
程序是用來睡眠的(TASK_INTERRUPTIBLE狀態下),直到@condition爲真,或者收到一個信號。
每次等待隊列@wq被喚醒時,檢查@condition;
若有可以改變等待條件的任何更改操作,調用wake_up();
如果@timeout超時,函數返回0;如果是被信號中斷,函數返回-ERESTARTSYS;
在超時之前condition 爲true,否則繼續剩餘的jiffies 。
理解所需:
1,TASK_INTERRUPTIBLE是可以被信號和wake_up()喚醒的,當信號到來時,進程會被設置爲可運行;而TASK_UNINTERRUPTIBLE只能被wake_up()喚醒。
2,信號是在軟件層次上對中斷機制的一種模擬,爲軟中斷。
3,signal_pending(current) :檢查當前進程是否有信號處理,返回值不爲0則表示有信號需要處理。
返回 -ERESTARTSYS 表示信號函數處理完畢後重新執行信號函數前的某個系統調用。(此函數只檢查是否有信號,不處理信號)
條件不滿足,則產生信號、開始等待。若返回非0,則表示沒有信號需要處理,繼續循環重新開始系統調用;若返回0,則表示有信號需要處理,直接處理數據,系統調用正常結束。
4,schedule_timeout()用來讓出CPU,在指定的時間用完以後或者其它事件到達並喚醒進程時(比如接收了一個信號量),該進程纔可以繼續運行.
[函數返回0表示timeout用完後被喚醒;返回整數表示timeout未用完時就被喚醒,此時可能接收到了一個信號量]
wait_event系列函數(作用:等待事件,置於休眠。區別從字面意思即可看出):
wait_event(queue, conditon);
wait_event_interruptible(queue, condition);
wait_event_timeout(queue, condition, timeout);
wait_event_interruptible_timeout(queue, condition, timeout);
*queue:作爲等待隊列頭的等待隊列被喚醒
*conditon:必須滿足,否則阻塞
*【timeout和conditon相比,有更高優先級】
參考內核源碼理解(在wait.h文件中)
#define __wait_event_interruptible_timeout(wq, condition, ret)
do {
DEFINE_WAIT(__wait);
for (;;) {
prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);
if (condition)
break;
if (!signal_pending(current)) {
ret = schedule_timeout(ret);
if (!ret)
break;
continue;
}
ret = -ERESTARTSYS;
break;
}
finish_wait(&wq, &__wait);
} while (0)
/**
* wait_event_interruptible_timeout - sleep until a condition gets true or a timeout elapses
* @wq: the waitqueue to wait on
* @condition: a C expression for the event to wait for
* @timeout: timeout, in jiffies
*
* The process is put to sleep (TASK_INTERRUPTIBLE) until the
* @condition evaluates to true or a signal is received.
* The @condition is checked each time the waitqueue @wq is woken up.
*
* wake_up() has to be called after changing any variable that could
* change the result of the wait condition.
*
* The function returns 0 if the @timeout elapsed, -ERESTARTSYS if it
* was interrupted by a signal, and the remaining jiffies otherwise
* if the condition evaluated to true before the timeout elapsed.
*/
#define wait_event_interruptible_timeout(wq, condition, timeout)
({
long __ret = timeout;
if (!(condition))
__wait_event_interruptible_timeout(wq, condition, __ret);
__ret;
})