sun的文檔對異步信號安全函數如下描述:
clearcase/" target="_blank" >cccccc">可以被信號控制器安全調用的函數被稱為異步信號安全函數。POSIX標準定義并 詳列了異步信號安全函數(IEEE Std 1003.1-1990.3.3.1.3(3)(f), page 55)。除 了POSIX異步信號安全函數外,下列三個函數也是異步安全的。
· sema_post(3T)
· thr_sigsetmask(3T)
· thr_kill(3T)
那份posix文檔我沒有找到,估計是過于古老;
但是需要安全的原因是和多線程的安全類似,關于共享資源的爭用和死鎖;
最基本的例子還是printf();
我的進程正在printf中,這時候被中斷了,中斷處理函數中使用了printf,
這樣,麻煩就來了;為什么呢;
因為剛才正在進行的那個printf鎖定了資源,信號處理函數中的這個printf就會被阻塞在那個鎖上面,
而且可悲的是永遠也沒有人能去把那個鎖給打開。55555555
所以在信號處理器中不要使用對共享資源加鎖的玩藝;
那么為什么單線程復制模型的fork也要求這種安全呢;
這種類型的函數在solaris線程庫中叫做fork1(2); 在posix線程庫中是fork(2);
他們在拷貝父進程的映像的時候僅僅拷貝調用fork函數的這個線程,其他的線程都被丟棄了;好慘。
還是拿printf;我的父進程中有一個線程正在printf();
這時候有一個線程進行了一次單線程復制模型的fork,于是它復制了一份自己,但同時它也復制了整個進程中的資源,包括那個正在被printf鎖定的鎖;麻煩又來了;
如果這個新的進程用遠不去碰那個鎖的話,就不會有事;但如果他多事,一定要去printf;
完蛋了,那個鎖是鎖住的,而且在這個進程里面并沒有那個上鎖的線程存在,也就是說,沒有誰會來解開這個鎖;
我等啊,我望穿了雙眼,等到天荒地老,等到??菔癄€;
大多數情況下,不會出現這種情況;那是因為這種類型的fork函數我們調用的目的就是在子進程里面調用exec();
而且絕大部分情況是fork()之后立即調用exec();所以沒問題;如果想多做些事情,就要小心了;
solaris線程庫fork(2);是多線程復制模型的,他會把整個進程中的所有線程一起復制,也就沒那個問題了;posix線程庫中沒有相應的函數;
但是posix線程庫提供了另一種接口 pthread_atfork(3T);這個函數要做三件工作,就是在fork之間將所有的鎖鎖住,在子進程中和父進程中分別在把鎖全都打開,也就解決了那個問題;
好像扯得有些遠,本來說信號安全的,結果扯上了fork();唉,反正被來就是從fork扯出來的;
原文轉自:http://www.anti-gravitydesign.com