关于异步信号安全

发表于:2007-05-26来源:作者:点击数: 标签:
引出我对这个东西重视的原因是sun的文档指出,在使用单线程复制模型fork1()或者posix标准的fork()时,在子进程中调用exec之前不要做任何操作,如果一定要做,尽量不要调用任何库函数,要做异步信号 安全 的操作; sun的文档对异步信号安全函数如下描述: 可
引出我对这个东西重视的原因是sun的文档指出,在使用单线程复制模型fork1()或者posix标准的fork()时,在子进程中调用exec之前不要做任何操作,如果一定要做,尽量不要调用任何库函数,要做异步信号安全的操作;

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.ltesting.net

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)