2013年1月21日 星期一

signal的省思

剛開始接觸signal沒多久,就一頭栽入了那些signal與訊號之間的關係,然後開始對應process生命週期與signal之間的聯繫,完全忽略了signal的本質asynchronous!!

asynchronous是一個"可怕"的詞,他有著可怕的效能以及不可捉摸的特性,人們最近對效能的貪婪在node.js可見一班,然後又發現他很難使用同步的功能甚至於說次序(order),很難確定事件之間發生的次序。

signal由於是asynchronous也就是表示他隨時會發生,所以不能對process做任何的假設,如果把signal拿來做為異常處理的手段之一,恐怕只有exit跟longjmp(結果通常也是跟著接exit)是說的上安全的。比方說,當一個process在執行malloc到一半的時候,被signal中斷,跟著signal裡面不管是使用該記憶體或者重新配置該記憶體,這都會引發不可臆測的問題

當然也可以介入更多的努力,力保signal產生的時候,這時process因為某些條件來說,是可以假定他沒有問題的,不過這通常伴隨著效能低落的問題

話說回來,很多programmer對signal的處理方式是忽略,少數採用類似cpu對deadlock的手法,也就是假設signal可以正常的運作,不正常的狀況很少,這是一個trade off

其實這也是一個reentrant的問題,在IBM的文章有討論到,的確有點難解
http://www.ibm.com/developerworks/linux/library/l-reent/index.html
或許最單調的處理方式就如文章內提到的使用sigprocmask()去block所有signal,形成一個critical section來保護

所以signal對unix/linux是必要的,因為這是系統機制的一部份,可是在使用上卻是要小心謹慎的,signal本質上應該是類似一個notify,而不應該再signal handler上處理太多的動作。

P.S. 一個有趣的定義是#define SIG_IGN ((void (*)(int))1);事實上我們應該不可能有address為0x1的pointer,這是隸屬於kernel space的地方,所以猜測應該是在kernel某個部分藉由判斷signal pointer為0x1就把它忽略吧,有人說在do_signal()這個function內,可是我在翻閱kernel的signal.c裡面卻沒有這個判斷式

參考資料:
http://zh.wikipedia.org/wiki/%E5%8F%AF%E9%87%8D%E5%85%A5

沒有留言:

張貼留言