2 等待一个全局变量被设置
这种情况是等待一个信号处理程序设置一个全局变量。下面的例子用于捕捉中断信号和退出信号,但是希望仅当退出信号处理程序时,才唤醒主进程。
#include
#include
#include
volatile sig_atomic_t quitflag;
/*
当把声明为该类型会保证该变量在使用或赋值时, 无论是在32位还是64位的机器上都能保证操作是原子的, 它会根据机器的类型自动适应。这个类型是定义在signal.h文件中。*/
static void sig_int(int signo)
{
if(signo == SIGINT)
printf("\ninterrupt\n");
else if(signo == SIGQUIT)
quitflag = 1;//等待这个全局变量
}
int main(void)
{
sigset_t newmask, oldmask, zeromask;
if(signal(SIGINT, sig_int) == SIG_ERR)
{
printf("signal(SIGINT) error");
exit(1);
}
if(signal(SIGQUIT, sig_int) == SIG_ERR)
{
printf("signal(SIGQUIT) error");
exit(1);
}
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT);
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)//屏蔽SIGQUIT信号
{
printf("SIG_BLOCK error");
exit(1);
}
while(quitflag == 0)
{
sigsuspend(&zeromask);//sigsuspend解开所有屏蔽信号,然后等待quitflag变成1,然后才往下执行,否则在这里循环
printf("quitflag = %d\n", quitflag);
}
quitflag = 0;
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
{
printf("SIG_SETMASK error");
exit(1);
}
exit(0);
}
由显示结果可以看出,sigsuspend放开屏蔽信号,按下“ctrl+C”,进入中断,但是不设置quitflag,直到按下“ctrl+\”,quitflag置1,才往下执行。
在单进程程序当中,主进程和中断共享变量,这不失为一种好办法。
3 父子进程通信,关于这个只有几个函数。在此不做记录。
另外重点说下sigaction函数:
int sigaction(int signo, const struct sigaction *restrict act, struct *restrictoact);
这个函数用来修改或者检查与指定信号相关联的处理动作,其中,参数signo是要检测或者修改其具体动作的信号编号,若act指针非空,
则要修改其动作,若oact非空,则系统由oact指针返回该信号的上一个动作。其中的结构体如下:
struct sigaction{
void (*sa_handler)(int);
sigset_t sa_mask;
int sa_flag;
void (*sa_sigaction)(int, siginfo_t *, void *);
};
关于这个函数可以这样理解:如果sa_handler字段有效,即这个字段是一个有效信号捕捉地址,则sa_mask字段信号集是这样的
在调用该捕捉函数前,这一信号集要加到进程的信号屏蔽字中,仅当从信号捕捉函数返回时再将进程的信号屏蔽字恢复到原来状态
这样,在信号处理函数调用时,就能阻塞某些信号,即在执行信号处理程序时,系统新建立的信号能被屏蔽,保证了在信号处理过程当中,
如果同一种信号再次发生,那么它会被阻塞到前一个新红处理完毕。例如:
int main(void)
{
int i = 0;
structsigactionact, oldact;
act.sa_handler = show_handler;
...
sigaddset(&act.sa_mask, SIGQUIT);
....
sigaction(SIGINT, &act, &oldact);
while(1) {
sleep(1);
printf("sleeping %d\n", i);
i++;
}}
上面函数设置SIGINT捕捉函数,在从SIGINT信号处理函数返回以前,把SIGQUIT信号屏蔽,从信号处理函数返回以后,恢复原来的信号屏蔽字。
这样即使在信号处理过程当中产生SIGQUIT信号,在接触屏蔽以后,信号SIGQUIT也能递达而不丢失。