Signal處理中的函數可重入問題

1. Signal信號簡介

信號是軟件層次上模擬的中斷,它是一種異步通信的處理機制。信號的異步性意味着,應用程序不用等待事件的發生,當信號發生時應用程序自動陷入到對應的信號處理函數中。產生信號的事件對進程而言是隨機出現的。信號的響應方式有忽略、捕捉、執行默認動作三種。

2. 線程安全

線程安全函數:在C語言中局部變量是在棧中分配的,任何未使用靜態數據或其他共享資源的函數都是線程安全的。使用全局變量的函數是非線程安全的。使用靜態數據或其他共享資源的函數,必須通過加鎖的方式來使函數實現線程安全。

線程安全的(Thread-Safe):如果一個函數在同一時刻可以被多個線程安全地調用,就稱該函數是線程安全的。線程安全函數解決多個線程調用函數時訪問共享資源的衝突問題。

3. 可重入

可重入(Reentrant)函數可以由多於一個線程併發使用,而不必擔心數據錯誤。可重入函數可以在任意時刻被中斷,稍後再繼續運行,不會丟失數據。可重入性解決函數運行結果的確定性和可重複性。

1)        一個函數對於多個線程是可重入的,則這個函數是線程安全的;

2)        一個函數是線程安全的,但並不一定是可重入的,比如使用互斥鎖實現的線程安全;

3)        可重入性要強於線程安全性。

4. Signal信號處理

信號處理函數中只能調用可重入函數,而不能調用不可重入函數。進程捕捉到信號並對其進行處理時,正在執行的正常指令序列就被信號處理程序臨時中斷,它首先執行該信號處理函數中的指令。如果從信號處理程序返回,則繼續執行在捕捉到信號時正在執行的正常指令序列(這類似於發生硬件中斷時所做的)。但在信號處理函數中,不能判斷捕捉到信號時線程執行到何處。

信號處理函數默認情況下是在進程的主線程調用的,這種情況下使用不可重入函數,有可能會造成不可預知的錯誤。比如調用了malloc函數,爲了保證malloc是線程安全的,所以內部使用了鎖,根據malloc中鎖的不同處理方式,分別可能會導致以下情況的發生:

1)        如果是普通鎖,在主線程中malloc函數獲取鎖之後被signal中斷,在signal處理函數中繼續調用malloc,因爲主線程中的malloc已經獲取到了鎖,signal處理函數只能等待鎖釋放,而主線程中的malloc函數正在等待signal處理函數返回後繼續執行,這樣就造成了鎖死;

2)        如果是遞歸鎖,那麼signal處理函數中的malloc函數獲取鎖後進行內存分配,因爲上次的malloc操作還沒完,可能成會造成內存數據混亂。

就定時而言,可不直接使用singal alarm,而使用posix定時器,通過通知線程的方式,將定時處理函數放到單獨的線程中來處理。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章