当初读《apue》的时候,有两个地方很难理解,一个是sigsuspend,另一个是posix条件变量,总是觉得半懂不懂的,这次尝试按照自己的理解把它们理清楚,不保证是正确的。
首先是sisuspend,首先是问题描述,为什么会出现这样一个函数?考虑书上这个例子:
int sig_int_flag main () { int sig_int (); ... signal (SIGINT, sig_int); ... while (sig_int_flag == 0) pause(); ... } sig_int () { signal (SIGINT, sig_int); sig_int_flag = 1; }
如果在测试sig_ing_flag 和 pause 之间产生了 SIGINT,那么程序将一直阻塞在pause调用中。
怎么解决这个问题呢? 怎么能让系统在sig_ing_flag 和 pause之间绝对不会产生SIGINT?或者把这个测试和pause合并成一个原子操作?
一个做法是,在测试sig_ing_flag之前屏蔽SIGINT,然后在pause期间解除SIGINT的屏蔽。
这正是sigsuspend的功能,在上面的例子中,只需要把pause替换成sigsuspend基本上就可以了
按照我的理解,sigsuspend 大概是这样工作的:
1 sigprocmask 屏蔽SIGINT
2 检查临界条件(我们不希望SIGINT打断这个条件,所以先屏蔽了)
3 调用sigsuspend, 其内部:
a.解除对SIGINT的屏蔽(通过传入一个空的sigset代替原来屏蔽的sigset)
b.等待信号出现,恢复对SIGINT的屏蔽
中断处理程序:执行信号处理函数
c.返回
4 临界条件已经满足,干活……
5 解除对SIGINT的屏蔽
举个应用场景:子进程要在父进程执行某个动作以后再执行,可以先sigsuspend,等待来自父进程的信号。
在多线程中对应的函数时pthread_sigmask 和 sigwait。 sigsuspend 和 sigwait略有不同,sigsuspend会把信号屏蔽字改为参数中的值,等待没有被屏蔽的信号,返回时恢复原来的信号屏蔽字;而sigwait 则是取消和等待参数中指定的信号屏蔽字,返回时恢复原来的信号屏蔽字。