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扯出来的;