2011-03-04 74 views
3

我想使用select()函數等待1秒,因爲我的程序使用信號來控制的東西,所以sleep()會過早返回。奇怪的是,當使用select()它也過早返回。使用睡眠和信號選擇

我打電話選擇這樣

struct timeval timeout;  
timeout.tv_sec = 10; 
timeout.tv_usec = 1000000; 
select (0 ,NULL, NULL, NULL, &timeout); 

但每當一個信號到達時,它會返回(我用的信號納米第二定時器)

任何人都知道這是爲什麼?

回答

5

嘗試是這樣的:

struct timespec timeout; 
timeout.tv_sec = 10; 
timeout.tv_nsec = 0; 
while (nanosleep(&timeout, &timeout) && errno == EINTR); 

的「剩餘時間」指針nanosleep將讓你重新啓動與睡眠,如果它被中斷剩餘時間的必要量的照顧。

+0

我會在星期一給我試一試,當我拿回電腦充電器時,但這應該可以工作。謝謝! – 2011-03-06 00:01:22

+0

是的,它在gprof的重度SIGPROF或SIGALRM下工作。 – osgx 2011-05-12 15:27:57

4

man 7 signal說:

系統的中斷調用和信號處理函數

庫函數如果在一個系統調用或庫 函數調用被阻塞的信號處理函數,然後 之一:

* the call is automatically restarted after the signal handler 
    returns; or 

    * the call fails with the error EINTR. 

以上哪兩種行爲發生取決於接口和 是否使用SA_RESTART標誌建立了信號處理程序 (請參閱sigaction(2))。 細節因UNIX系統而異 - tems;下面是Linux的細節。

如果下列接口中的一個封端的調用由信號處理器中斷 ,然後 的 呼叫將被自動如果 回報被 使用SA_RESTART標誌信號處理程序後重新開始;否則該呼叫將失敗,並出現錯誤EINTR

通常,檢查返回值是否爲-1並且errno == EINTR,然後重新調用該函數是糾正此問題的正確方法。

+1

這個答案不完整,不是OP的問題。 Linux對信號(可重新啓動的系統調用)具有理想的BSD行爲,但是當信號中斷時,即使信號處理程序安裝了SA_RESTART,它也會作爲*特性*被選擇* *總是*返回。這個想法是,程序可能(可能確實)想要接收一個信號,就像它會對IO準備好的文件描述符一樣。 – 2011-03-04 21:10:37

+1

我認爲這是對第二個答案的解釋。我正在做的是使用一個信號跟蹤時間,試圖模仿微處理器的時鐘中斷接口。所以信號實際上每納秒調用一次,遞增一個時間計數器。這是做這件事的壞方法嗎?使用完全相同的信號可能會有100多個進程在同一時間運行。 我正在使用timer_create和CLOCK_PROCESS_CPUTIME_ID爲clockid_t創建一個計時器 – 2011-03-06 00:10:43