2010-07-13 53 views
0

我目前使用select()作爲計時器。我有一個循環內發生的網絡接收操作,並且每隔幾秒需要發生一次處理操作。SIGALRM超時 - 它如何影響現有的操作?

結果,選擇()語句的超時不斷變化 - 隨着時間的推移下降到零,然後在3

rv = select(selectmonitor+1, &readnet, NULL, NULL, &helper.timeout());

由於事情來在網絡上重新啓動,語句重複並且由helper.timeout()傳遞給它的值減少。最終,該值將等於零或系統將超時,這將導致處理函數執行。但是,我注意到這是相當耗費資源的 - 必須不斷計算helper.timeout()的值。當我試圖每秒接收數千個數據包時,執行此操作所需的時間會導致數據包丟失。

我的新想法是使用SIGALRM來解決這個問題。這將允許我設置一個計時器,然後在啓動時作出反應。但是,我很困惑它會如何影響我的程序。當SIGALRM'關閉'時,它將運行我指定的函數。但是,它將如何中斷我現有的代碼?一旦完成該功能,我現有的代碼(在while語句中)將如何恢復?

此外,它似乎不可能設置SIGALRM信號調用類中的函數?它是否正確?我想我可以調用一個函數,這個函數又可以調用一個類中的函數..

感謝您提前提供任何幫助。

回答

1

使用您的SIGALRM處理程序來設置標誌變量。

使用sigaction而不是signal來設置您的信號處理程序。不要設置SA_RESTART標誌。用SA_RESTART 而不是設置你的select語句會被信號中斷。您的選擇將返回-1,errno將爲EINTR。

由於信號可能發生,而您的其他代碼正在執行,您將需要檢查標誌變量,可能就在進入選擇之前。

我剛剛被提醒說,如果這種模式剛剛在檢查標誌之後並且在進入選擇之前發生,可能會導致信號丟失。

爲了避免這種情況,您需要使用sigprocmask在進入while循環之前阻止SIGALRM信號。然後您使用pselect而不是select。通過給予pselect一個帶有SIGALRM掩碼的信號掩碼,信號將在選擇期間始終中斷,而不是在任何其他時間發生。

+1

爲了補充說明,使用信號(alarm())會導致很多其他系統調用「失敗」,並且如果在執行系統調用時警報關閉,則也將errno設置爲EINTR - 應該是照顧 – nos 2010-07-13 21:33:27

+0

@贊 - 你的回答有點混亂:「不要使用SA_RESTART標誌,你的選擇語句將被信號中斷」。你是說如果我不使用SA_RESTART標誌,我的select語句會被中斷嗎?或者這兩件事是分開的。 – BSchlinker 2010-07-13 21:56:22

+0

@nos - 你是否建議先前使用select()來安排超時的方法更好? – BSchlinker 2010-07-13 22:32:05