signal_pending與返回-ERESTARTSYS

 

經常我們在睡眠的代碼中 會看到這樣的例子:

    if (signal_pending(current)) {

     ret = -ERESTARTSYS;

     return ret;

    }

    關於 -ERESTARTSYS 到底是什麼意思? 

 

     -ERESTARTSYS表示信號函數處理完畢後重新執行信號函數前的某個系統調用.
也就是說,如果信號函數前有發生系統調用,在調度用戶信號函數之前,內核會檢查系統調用的返回值,看看是不是因爲這個信號而中斷了系統調用.如果返回值 -ERESTARTSYS,並且當前調度的信號具備-ERESTARTSYS屬性,系統就會在用戶信號函數返回之後再執行該系統調用

 

    這個過程,不必深究,你就知道上層的庫函數 ,當收到 -ERESTARTSYS這個返回值後,對於linux來講,會自動的重新調用這個調用就可以了。

至於
signal_pending( current )―――》檢查當前進程是否有信號處理,返回不爲0表示有信號需要處理。

情景分析:
1,當一個系統調用處於等待狀態時,比如等待輸入緩衝區不爲空,此時產生了信號,這個信號僅僅是在該進程的thread_info結構中標識一下,就是所謂的“發信號”,然後喚醒進程的系統調用,系統調用醒來後,此時僅僅用signal_pending()檢查一下是否有信號,這裏,不處理信號的,當此時有信號,系統調用返回ERESTARTSYS,在從系統調用的返回用戶空間時,會根據thread_info中信號標識位調用相應的信號處理函數,這裏就是所謂的“接收信號”,
對於Linux,上層庫函數會根據系統調用的ERESTARTSYS返回值重啓該系統調用,而對於Solaris則會讓系統調用失敗,在Linux中,重啓的系統調用會再次檢查緩衝區,爲空,說明剛纔的信號不是緩衝區有數據了的信號,繼續等待,重複剛纔的過程,不爲空,就可以直接處理數據,系統調用正常結束
注:“發信號”僅僅是標識thread_info,系統調用醒來檢查信號,僅僅是
signal_pending()判斷一下thread_info中是否有任何一個信號標識,真正的“接受信號”是從系統調用返回時,或者異常處理程序返回時,比如每次的時鐘中斷處理函數返回時,檢查thread_info中具體哪個信號,調用相應處理程序
補:對於Solaris,上面的情況,read在等,緩衝區滿了,喚醒read進程,不同通過我們這裏所談的“信號”



檢測進程p是否有待處理的信號(p->thread_info->flags中TIF_SIGPENDING位是否置位)
-----------------------------------------------------
static inline int signal_pending(struct task_struct *p)
{
 
   return unlikely(test_tsk_thread_flag(p, TIF_SIGPENDING));
}
#define TIF_SIGPENDING      2  



-----------------------------------------------------
static inline int test_tsk_thread_flag(struct task_struct *tsk, int flag)
{
    return test_ti_thread_flag(task_thread_info(tsk), flag);
}



-----------------------------------------------------
static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
{  
    return test_bit(flag, &ti->flags);
}




檢測addr的第nr位是否爲1(addr右起最低位爲第0位)
-----------------------------------------------------
static inline int test_bit(int nr, const volatile void * addr)
{  
    return (1UL & ( ((const int *) addr)[nr >> 5] >> (nr & 31) ) ) != 0UL;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章