2017-02-28 123 views
0

我不認爲這是重複的。我有一個非常具體的問題,當調用一個信號處理程序時,其他線程會發生什麼。Linux:信號對多線程的影響

我有一個使用硬件的多線程程序。在獲取SIGTERM(來自父進程)時,我希望信號處理程序將硬件的狀態設置爲給定狀態,然後退出(1)。我明白,因爲我沒有使用信號掩碼,所以主線程會處理信號。但是它是一個多處理器系統(樹莓派),其他線程都以高優先級運行。他們可能是睡着了,但他們也可能會碰到硬件。

如果所有其他線程在信號到達時凍結,我很好 - 我直接從信號處理程序調用exit(),其他線程永遠不會再運行。但是如果它們可以獨立運行,那麼在處理程序中設置了所需的狀態之後,但在退出之前,它們可能會與硬件有關。而且我找不到描述效果的文檔。如果「凍結一切,但信號處理程序」不是默認的,是否有辦法獲得該行爲?

我可以重新設計代碼,將所有硬件處理放在一個線程中,並讓該線程處理中斷,但這很不方便 - 我現在擁有的線程佈局做了很好的分工,每個線程都知道它可以使用哪些硬件觸摸和什麼時候。我寧願不重新設計。

回答

1

其他線程將在信號處理線程運行時繼續運行。我不知道任何凍結一切機制。

但是,如果你有多個線程操縱硬件,看起來你應該有某種互斥機制。實際上:

pthread_mutex_lock(&hardware_lock); 
fiddle_with_hardware(); 
pthread_mutex_unlock(&hardware_lock); 

然後,你可以有你的信號處理線程獲取鎖,重置硬件狀態,並呼籲exit沒有釋放鎖。調用exit將終止所有線程,並且由於鎖被保持,在終止之前沒有其他線程能夠與硬件混淆。

如果您有多個線程全部操縱整個硬件狀態的離散部分,則可以爲每個狀態部分創建一個單獨的鎖。然後讓您的信號處理線程在設置最終硬件狀態並調用exit之前獲取鎖的所有的所有。由於在普通操作中,將只有一個線程試圖訪問狀態的每個離散部分,因此額外的鎖定應該沒有可衡量的性能影響。

另一件事。我認爲這是不準確的,「因爲我沒有使用信號掩模,主線程會處理信號。」從pthreads(7)

根據POSIX.1,處理向信號(使用kill(2)發送,例如)應該由進程內的單個,任意選擇的線程來處理。

這意味着你應該使用pthread_sigmask以確保SIGTERM指向主線程。

+0

不過,在信號處理程序中不能做到「讓你的信號處理線程獲得鎖定」,但在信號處理程序中使用互斥體是不安全的。 – nos

+0

@nos好點。最好讓信號處理程序設置一個標誌,並在從信號處理程序返回後執行其餘的操作。 –

+0

這就是我所害怕的。我知道我無法做互斥體解決方案(我的擔心之一是wiringPi在封面下使用了互斥體,這將使任何解決方案無法單線程訪問硬件)。我可能不得不重新設計。謝謝。 – user15001