2012-03-04 89 views
3

有人可以解釋爲什麼我們不應該從信號處理程序調用非異步函數嗎?就像在用這種功能調用時破壞程序的確切步驟一樣。 而且,信號是否總是在單獨的堆棧上運行?如果是這樣,它是一個單獨的上下文,或者它在信號線程的上下文上運行? 最後,在多線程系統的情況下,當信號處理程序被執行並且一些其他線程被髮信號並調用相同的信號處理程序時會發生什麼?我試圖發展對信號及其應用的深刻理解。信號處理 - 異步函數和多線程應用程序,信號棧

回答

2

當進程接收到一個信號,它是在方法的上下文中進行處理。您應該只使用信號處理程序內的同步安全函數或重入函數。例如,您不能在信號處理程序中調用malloc()或printf()。原因是:

*)讓我們假設你的進程在malloc中執行,當你收到信號。所以全局堆數據結構處於不一致的狀態。現在,如果您從信號處理程序中獲取堆鎖並進行更改,則會進一步渲染堆不一致。

*)另一種可能是,如果堆鎖已被您的進程在接收到信號時獲取,然後您從信號處理程序中調用malloc(),則會看到該鎖被保持並等待無限獲取鎖定(無限制,因爲可以釋放鎖的線程在信號完全處理之前不會運行)。

2)信號在過程的上下文中運行。至於信號堆棧,你可以看看這個答案 - >Do signal handers have a separate stack?

3)至於獲得同一信號的多個實例,你可以看看這個鏈接 - >Signal Handling in UNIX哪裏Rumple Stiltskin回答得很好。

+0

詳細闡述第一點,信號是半軟件中斷,因此會異步到達。內核在線程中斷時保存一些寄存器(所以它會知道回到哪裏等),運行處理程序然後返回。信號處理程序中的阻塞調用可能會導致死鎖,因爲您無法控制此類信號何時到達。這就是說,還有其他可能導致這種僵局的行爲,以及許多避免它們的選擇。但即使可以避免死鎖,在信號環境中做太多處理也是一種不好的做法(與中斷相同)。 – EdwardH 2012-03-05 07:59:24

0

我知道一些Solaris。所以我正在使用它的細節。 LWP ==用於「thread」的Solaris與pthread一樣。

像SIGILL這樣的陷阱信號被傳送到導致陷阱的線程。異步信號被傳送到第一個活動線程(LWP),或不阻塞該信號的進程。稱爲aslwp()的內核模塊遍歷進程頭表(具有關聯的LWP),尋找第一個可能的候選接收異步信號。

信號棧位於內核中。我不確定什麼/如何回答你的信號棧問題。 一個進程可能有幾個未決信號。你是這個意思嗎?

發往某個進程的每個信號都保存在該進程中,直到該進程將上下文(或強制)切換到活動狀態。這部分是因爲當進程上下文被換出並且進程沒有任何cpu方式時,通常不會產生陷阱。你當然可以招致異步信號。但是如果無法運行,該進程不能對任何信號「做任何事情」。所以,此時內核將上下文交換回活動狀態,並通過aslwp()傳遞信號。

實時信號的行爲不同,我讓它留下來。

嘗試閱讀本:

developers.sun.com/solaris/articles/signalprimer.html