由上篇alarm()与pause()函数实现的简单sleep()函数,我们可以发现一个问题。当进程执行完alarm()函数之后,还没来得及执行pause()函数,就失去cpu(内核去执行其他程序)。再alarm()计时结束后,本程序才得到cpu,执行pause()函数。这时会发现本进程永远都会在pause()函数执行的挂起状态,退不出来。
解决办法:可以通过设置屏蔽SIGALRM,将执行挂起状态与解除屏蔽绑定在一起(原子操作)。
sigsuspend()函数:执行期间用自己的mask覆盖阻塞信号集,执行结束恢复阻塞信号集
原型:int sigsuspend(const sigset_t *mask);
头文件:#include<signal.h>
24 #include<stdio.h>
25 #include<unistd.h>
26 #include<signal.h>
27 #include<errno.h>
28 void wake(int argc)
29 {
30 printf("i wake up\n");
31 }
32 void main(void)
33 {
34 int ret;
35 sigset_t newset,oldset,suspset;
36 alarm(5);//计时器计时5秒
37 signal(SIGALRM,wake);//注册捕捉函数
38 sigemptyset(&newset); 添加对应的阻塞信号
39 sigaddset(&newset,SIGALRM);
40 sigprocmask(SIG_BLOCK,&newset,&oldset);
41 sigdelset(&newset,SIGALRM);
42 suspset=newset;
43 sigsuspend(&suspset);//挂起并且将SIGALRM临时从阻塞信号集中解除屏蔽
44 while(1);
45 //恢复阻塞信号集原本的设置
46 sigprocmask(SIG_SETMASK,&oldset,NULL);
47 //取消计时器
48 alarm(0);
49 }