NAME
sigsuspend, rt_sigsuspend - wait for a signal
SYNOPSIS
#include <signal.h>
int sigsuspend(const sigset_t *mask);
功能:以下三步为原子操作
第一步:设置当前进程信号集状态为 目标信号集状态mask,并保存进程旧的信号集状态为 oldmask
第二步:马上进入等待信号阶段
第三步:收到信号唤醒后 设置当前进程信号集状态为 旧的信号集状态oldmask。
实验1,用pause()实现,打印一行*后 ,停止等待信号 驱动程序继续跑
pause()休眠 等待信号唤醒,CTRL+C 唤醒程序执行打印下一行
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void sig_handler(int s)
{
write(1,"!",1);
}
int main()
{
int i,j;
sigset_t set,saveset;
signal(SIGINT,sig_handler);
sigemptyset(&set);
sigaddset(&set,SIGINT);
sigprocmask(SIG_UNBLOCK,&set,&saveset);
for(j=0;j < 1000;j++)
{
sigprocmask(SIG_BLOCK,&set,NULL);
for(i=0 ; i<5 ; i++)
{
write(1,"*",1);
sleep(1);
}
write(1,"\n",1);
sigprocmask(SIG_UNBLOCK,&set,NULL);
pause();
}
sigprocmask(SIG_SETMASK,&saveset,NULL);
exit(0);
}
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ ./a.out
*****
^C!*****
^C!*****
^C!****^C*
!^\Quit (core dumped)
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$
问题:
程序确实可以在打印一行后 暂定,等待 SIGINT 后再 打印下一行*。
但是,发现,如果在当前行打印途中 发送 SIGINT信号,不会驱动程序打印下一行数据,这是因为
在
sigprocmask(SIG_UNBLOCK,&set,NULL); pause()
这两个函数中间,当解除信号阻塞之后,还没来得及执行pause(),就把 SIGINT信号响应掉了,所以信号就作用不到 pause(),即不会唤醒进程,程序响应 SIGINT信号之后,打印!再执行到 pause()。 我们知道,程序在运行当中 可以理解为 时时刻刻都在被中断,时间片一直在反复的耗尽,也就是反复 进入内核态等待调度,再继续执行程序,所以此时 刚刚好从内核态切换回用户态,发现SIGINT信号,于是马上响应信号动作。我们的初衷是 执行完解除阻塞后,马上pause()挂起,最后SIGINT信号作用到 pause()上,打印下一行 ,
所以 这个问题的原因就是 sigprocmask(SIG_UNBLOCK,&set,NULL) 与 pause() 这两个操作组合 是非原子操作,是不原子的。
修改:用 sigsuspend()实现
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void sig_handler(int s)
{
write(1,"!",1);
}
int main()
{
int i,j;
sigset_t set,saveset,oset;
signal(SIGINT,sig_handler);
sigemptyset(&set);
sigaddset(&set,SIGINT);
sigprocmask(SIG_UNBLOCK,&set,&saveset);
sigprocmask(SIG_BLOCK,&set,&oset);
for(j=0;j < 1000;j++)
{
for(i=0 ; i<5 ; i++)
{
write(1,"*",1);
sleep(1);
}
write(1,"\n",1);
sigsuspend(&oset);
}
sigprocmask(SIG_SETMASK,&saveset,NULL);
exit(0);
}
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ gcc sigsuspend.c
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$ ./a.out
*****
^C!*****
^C!**^C*^C^C**
!*****
^C!**^\Quit (core dumped)
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/signal/test$
可以实现目标功能。