sigpending函数
sigpending函数返回一个被当前进程阻塞的信号集,这个信号集通过set参数返回。
|
例子:
Figure 10.15. Example of signal sets and sigprocmask#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 */
if (sigpending(&pendmask) < 0)
err_sys("sigpending error");
if (sigismember(&pendmask, SIGQUIT))
printf("\nSIGQUIT pending\n");
/*
* Reset 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");
}
|
Figure 10.15显示了很多我们描述过的信号功能。
进程阻塞了SIGQUIT信号,保存了当前的信号掩码(用于之后重置),然后休眠5秒钟。在进程运行期间发生的任何退出信号都会被阻塞,直到解除阻塞才会被传送。
注意,当我们阻塞了信号时保存了旧的信号掩码。解除阻塞时我们要对旧的掩作SIG_SETMASK操作。或者,我们也可以只对阻塞的信号做SIG_UNBLOCK操作。要知道如果我们写了一个函数,它能被其它函数调用,并且我们需要在我们的函数中阻塞一个信号,无论如何我们都不能通过SIG_UNBLOCK去解锁该信号。在这种情况下,我们必须使用SIG_SETMASK并且重置信号掩码到它之前的值,因为调用者可能在我们调用函数之前就已经阻塞了这个信号。稍后10.18节介绍system函数时会看到相关的例子。
如果在函数休眠阶段产生了退出信号,那么这个退出信号并不被阻塞,所以它会在sigprocmask返回之前被传递到进程。我们将会看到它发生,因为在信号处理函数中的printf会在sigprocmask后面的printf之前输出。
进程休眠5秒钟,用于干其它的事情。如果我们在休眠其间产生了退出信号,这个信号交会终止进程,因为当捕获该信号时,我们重置信号的动作为默认。看下面的输出,终端打印^\代表终端退出字符:
$ ./a.out
^\ generate signal once (before 5 seconds are up)
SIGQUIT pending after return from sleep
caught SIGQUIT in signal handler
SIGQUIT unblocked after return from sigprocmask
^\Quit(coredump) generate signal again
$ ./a.out
^\^\^\^\^\^\^\^\^\^\ generate signal 10 times (before 5 seconds are up)
SIGQUIT pending
caught SIGQUIT signal is generated only once
SIGQUIT unblocked
^\Quit(coredump) generate signal again
|