sigpending函数返回被阻塞而为调用进程待定的信号。信号集通过set参数返回。
- #include <signal.h>
- int sigpending(sigset_t *set);
- 成功返回0,错误返回-1
下面的代码展示了我们描述过的所有信号的特性。
- #include <signal.h>
- static void sig_quit(int);
- int
- main(void)
- {
- sigset_t newmask, oldmask, pendmask;
- if (signal(SIGQUIT, sig_quit) == SIG_ERR) {
- printf("can't catch SIGQUIT");
- exit(1);
- }
- /*
- * Block SIGQUIT and save current signal mask.
- */
- sigemptyset(&newmask);
- sigaddset(&newmask, SIGQUIT);
- if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
- printf("SIG_BLOCK error\n");
- exit(1);
- }
- sleep(5); /* SIGQUIT here will remain pending */
- if (sigpending(&pendmask) < 0) {
- printf("sigpending error\n");
- exit(1);
- }
- if (sigismember(&pendmask, SIGQUIT))
- printf("\nSIGQUIT pending\n");
- /*
- * Reset signal mask which unblocks SIGQUIT.
- */
- if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
- printf("SIG_SETMASK error\n");
- exit(1);
- }
- 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) {
- printf("can't reset SIGQUIT\n");
- exit(1);
- }
- }
进程阻塞了SIGQUIT,保存它当前的信号掩码(以便稍后重置),然后睡眠5秒。在此期间的任何退出信号的发生都不会被分发,直到信号被反阻塞。在5秒的睡眠后,我们检查信号是否待定并反阻塞这个信号。
注
意我们在阻塞信号前保存了老的掩码。为了反阻塞信号,我们执行了老掩码的SIG_SETMASK。另一种方式,我们可以只SIG_UNBLOCK我们已经
阻塞的信号。然而,要知道如果我们写了一个可以被其他调用的函数,且我们需要在我们的函数里阻塞一个信号,那么我们不能使用SIG_UNBLOCK来反阻
塞这个信号。在这种情况下,我们必须使用SIG_SETMASK并把信号掩码重置为它之前的值,因为调用者在调用我们的函数前可能已经阻塞了这个信号。我
们将在10.18节里的system函数里看到一个这样的例子。
如果我们在睡眠期产生退出信号,那么信号现在是待定而无阻塞的,所以它在sigprocmask返回值被分发。我们将看到这个发生因为信号处理器里的printf在sigprocmask调用后面的printf之前输出。
进程然后又睡了5秒。如果我们在这个睡眠期间产生了退出信号,那么信号应该终止这个进程,因为我们在捕获到它后把这个信号重置到默认值。在下面的输出里,当我们输入终端退出符Control-backslash时终端打印出^\:
$ ./a.out
^\
SIGQUIT pending
caught SIGQUIT
SIGQUIT unblocked
$ ./a.out
^\^\^\^\^\^\^\^\^\^\
SIGQUIT pending
caught SIGQUIT
SIGQUIT unblocked
注意第二次运行程序时我们在进程睡眠时产生了十倍的退出信号,但是信号在被反阻塞后只被分发给了进程一次。这证明了信号没有在这个系统上排队。
阅读(2425) | 评论(0) | 转发(0) |