2011-12-21 51 views
0

我看到在我的應用程序were not always working as expected信號量。然後我被告知,當信號中斷sem_wait呼叫時,可能會導致此意外行爲。什麼照顧信號的存在

所以,我的問題是程序員在有信號時需要注意什麼。對於sem_wait,我們可以檢查返回值,但對於所有非異步安全函數,這是否一樣?當期望信號中斷我們的代碼時,我們還應該記住什麼?

回答

2

UNIX信號是一種蠕蟲病毒,只是爲了說明這一點。

有2個關於系統調用和信號的陣營。

  • 的SysV/POSIX語義:系統調用被信號中斷,他們返回一個錯誤,並設置errno爲EINTR
  • BSD語義的系統調用是如果發生信號自動重新啓動(當然,其中大部分是無論如何,一些不是,例如select/poll/sleep)。

使用signal()時,缺省值爲上述兩者之一,BSD系統和Linux默認爲BSD語義,並且每個人[需要的引用]都具有SysV語義。 (在Linux上,這取決於很多因素,例如用-std = C99編譯給人SysV的語義,與-std = gnu99給BSD語義。例如參見http://www.gnu.org/s/hello/manual/libc/Interrupted-Primitives.html

當您安裝使用sigaction的信號處理器()您可以選擇使用SA_RESTART標誌的語義。

基本上是:

  • 不要使用信號,如果你能幫助它。
  • 如果可以,請使用BSD語義。
  • 對於需要可移植並處理信號的代碼,您需要將每個系統調用包裝在一個循環中,以檢查調用失敗,檢查errno是否爲EINTR並再次執行系統調用(或者根據捕獲信號)。
  • 庫調用可以使用信號,即使您的代碼沒有。
  • 系統調用通常使用SysV/Posix語義,將返回-1並將errno設置爲EINTR。但請閱讀文檔以瞭解錯誤情況。

編輯:編輯,因爲我混淆了BSD vs Sysv語義。

+0

因此,如果SysV自動重新啓動一個系統調用,那麼爲什麼sem_wait沒有得到重新啓動,因爲它有時會給出錯誤代碼? – MetallicPriest 2011-12-21 12:15:43

+0

@MetallicPriest你是否100%肯定它不?無論如何,我希望有一個列表,確切地說哪些系統調用不是自動重新啓動的,即使是使用sysv語義。 sem_wait可能就是其中之一。 – user964970 2011-12-21 12:19:16

+0

對於任何給定系統調用的默認中斷操作應記錄在系統的聯機幫助頁中。如果您使用的是Linux系統,並且沒有發生任何異常情況,那麼您的系統調用應該在被信號中斷後透明地重新啓動。 – 2011-12-21 14:18:58