2013-11-25 28 views
1

我在ucLinux上爲套接字通信編寫代碼。我使用select()來讀取套接字上的數據。我也有一個20毫秒的定時器(使用setitimer創建)運行在同一線程中執行並行操作。每次選擇「被系統調用中斷」時,我的選擇函數都會被阻塞,因爲它每20毫秒就會收到定時器在溢出時發出的SIGALRM信號問題。 EINTR發佈後,我嘗試重新啓動系統,然後再次運行select()。但這不會有幫助,因爲我會每隔20毫秒就會收到定時器的SIGALRM。我不想忽略這個信號,因爲它用於執行系統中的其他任務,但是我想使用select而不受此信號的影響。有什麼辦法可以解決這個問題嗎?我無法使用像timer_create()這樣的功能,因爲這些功能在我使用的平臺上不受支持。所以,我堅持使用setitimer來創建定時器。有什麼辦法可以在我的代碼中獨立運行嗎?在同一個linux線程中運行select()套接字和定時器

回答

1

是否有這樣的選擇?

While(1) { 
    int rc = select(nfds, &readfds, &writefds, &exceptfds, &timeout); 
    if ((rc < 0) && (errno == EINTR)) 
     continue; 
    else { 
     // some instructions 
    } 
} 

如果這是不是你指定一組應在PSELECT()期間不被阻止信號的選項,您也許可以使用PSELECT增加了一個參數來結束(sigmask),見here

+0

嗨, 感謝您的建議。我已經這樣做了。但問題是它在select中保持循環,因爲它在每20毫秒(即定時器在同一線程上運行的時間)之後始終由系統獲取EINTR。因此,我有一個選擇函數可以繼續運行,中斷並且再次運行,並且最終最終在套接字上讀取任何內容,只是保持循環發出中斷的呼叫信號。 有什麼辦法可以避免這種情況?我需要定時器在同一個線程中,我不能忽略定時器信號,也不能阻止選擇功能。任何方式實現兩者? – user2069669

+0

@ user2069669增加了對pselect的引用,你可以使用而不是select – Jekyll

2

你在做什麼很奇怪。讓我們面對現實吧:定時器是一個古老的,大多數已經過時的工作機制。現在幾乎每個人都避免像鼠疫這樣的信號。在信號回調中基本上沒什麼用處(你當然不能像malloc那樣調用任何複雜的東西),所以你必須有一些方法讓計時器通知從SIGALRM處理程序返回到主線程 - 你實際上做信號處理器的工作是你嗎?

所以你有兩種策略:使用標準的自管式技巧將信號轉化爲fd上的事件,這是處理諸如SIGTERM,SIGINT等事件的「常規」方式。您可以撥打socketpairpipe來製作管道,然後從信號處理程序中向管道中寫入一個字節。你從你的select循環讀回字節。你通常把信號的值寫成數據,但你可以真的寫任何東西。

另一種策略(更理智)是完全避免信號和setitimer的混亂。 setitimer是嚴重的遺留問題,並導致各種問題(例如,它可能導致像getaddrinfo這樣的函數掛起,glibc中仍然沒有修復的錯誤(http://www.cygwin.org/frysk/bugzilla/show_bug.cgi?id=15819)。信號對您的健康有害。因此,「normal 「策略是使用超時參數select您有一個定時器的鏈表,用於管理代碼中定期事件的對象。當您撥打select時,將使用剩餘定時器中最短的時間作爲超時值。當select調用返回,你檢查是否有定時器過期,並調用定時器處理程序以及你的fd事件處理程序,這是一個標準的應用程序事件循環,這樣你的循環代碼就可以監聽定時器驅動的事件以及fd驅動事件幾乎系統上的每個應用程序都在此機制上使用某種變體

相關問題