?: sigpending函数返回一信号集,对于调用进程而言,其中的各信号是阻塞不能递送的,因而也一定是当前未决的。该信号集通过set参数返回。
#include <signal.h>
int sigpending(sigset_t *set);
//返回值:若成功,返回0;若出错,返回−1
实例
图10-15展示了很多前面说明过的信号功能。
#include "apue.h"
static void sig_quit(int);
int
main(void)
{
sigset_t newmask, oldmask, pendmask;
if (signal(SIGQUIT, sig_quit) == SIG_ERR)
err_sys("can't catch SIGQUIT");
/*
* Block SIGQUIT and save current signal mask.
*/
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT);
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
err_sys("SIG_BLOCK error");
sleep(5); /* SIGQUIT here will remain pending */
//进程阻塞SIGQUIT信号,保存了当前信号屏蔽字(以便以后恢复),然后休眠5秒。
//在此期间所产生的退出信号SIGQUIT都被阻塞,不递送至该进程,直到该信号不再被阻塞。
//在5秒休眠结束后,检查该信号是否是未决的,然后将SIGQUIT设置为不再阻塞。
if (sigpending(&pendmask) < 0)
err_sys("sigpending error");
if (sigismember(&pendmask, SIGQUIT))
printf("\nSIGQUIT pending\n");
/*
* Restore signal mask which unblocks SIGQUIT.
*/
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
printf("SIGQUIT unblocked\n");
sleep(5); /* SIGQUIT here will terminate with core file */
exit(0);
}
static void
sig_quit(int signo)
{
printf("caught SIGQUIT\n");
if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
err_sys("can't reset SIGQUIT");
}
图10-15 信号设置和sigprocmask实例
进程阻塞SIGQUIT
信号,保存了当前信号屏蔽字(以便以后恢复),然后休眠5秒。
在此期间所产生的退出信号SIGQUIT
都被阻塞,不递送至该进程,直到该信号不再被阻塞。在5秒休眠结束后,检查该信号是否是未决的,然后将SIGQUIT
设置为不再阻塞。
注意,在设置 SIGQUIT
为阻塞时,我们保存了老的屏蔽字。为了解除对该信号的阻塞,用老的屏蔽字重新设置了进程信号屏蔽字(SIG_SETMASK
)。另一种方法是用SIG_UNBLOCK
使阻塞的信号不再阻塞。但是,应当了解如果编写一个可能由其他人使用的函数,而且需要在函数中阻塞一个信号,则不能用SIG_UNBLOCK
简单地解除对此信号的阻塞,这是因为此函数的调用者在调用本函数之前可能也阻塞了此信号。在这种情况下必须使用SIG_SETMASK
将信号屏蔽字恢复为先前的值,这样也就能继续阻塞该信号。10.18节的system函数部分有这样的一个例子。
在休眠期间如果产生了退出信号,那么此时该信号是未决的,但是不再受阻塞,所以在sigprocmask 返回之前,它被递送到调用进程。
从程序的输出中可以看到这一点:SIGQUIT
处理程序(sig_quit)中的printf语句先执行,然后再执行sigprocmask之后的printf语句。
然后该进程再休眠5秒。如果在此期间再产生退出信号,那么因为在上次捕捉到该信号时,已将其处理方式设置为默认动作,所以这一次它就会使该进程终止。在下列输出中,当我们在终端键入退出字符Ctrl+\时,终端打印^\(终端退出字符):
$ ./a.out
^\ 产生信号一次(在5s之内)
SIGQUIT pending 从sleep返回后
caught SIGQUIT 在信号处理程序中
SIGQUIT unblocked 从sigprocmask返回后
^\Quit(coredump) 再次产生信号
$ ./a.out
^\^\^\^\^\^\^\^\^\^\ 产生信号10次(在5 s之内)
SIGQUIT pending
caught SIGQUIT 只产生信号一次
SIGQUIT unblocked
^\Quit(coredump) 再产生信号
shell发现其子进程异常终止时输出QUIT(coredump)信息。
注意,第二次运行该程序时,在进程休眠期间使SIGQUIT信号产生了10次,但是解除了对该信号的阻塞后,只向进程传送一次SIGQUIT。从中可以看出在此系统上没有将信号进行排队。