linux內核--wait_event_interruptible_timeout()函數分析

網上有關於此函數的分析,但大都是同一篇文章轉載來轉載去,沒有進一步的分析。做個小結:

瞭解函數功能,除了直接看代碼邏輯,最有效的當是註釋內容了。
如下:

函數原型: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;                              
})
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章