sigpending() 函数原型如下:
[C++] 纯文本查看 复制代码 #include <signal.h>
int sigpending(sigset_t *set);
当信号被调用进程阻塞而不能递送时,这些信号是未决信号,它们可以通过 sigpending() 函数的参数 set 返回。
测试代码:
[C++] 纯文本查看 复制代码 #include <stdio.h>
#include <stdlib.h>
#include <signal.h>
static void sig_quit(int signo)
{
printf ("caught SIGQUIT\n");
if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) {
printf ("Can't reset SIGQUIT)");
exit (EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
printf ("My pid : %d\n", (long)getpid());
sigset_t newmask, oldmask, pendmask;
if (signal(SIGQUIT, sig_quit) == SIG_ERR) {
perror("signal");
exit (EXIT_FAILURE);
}
//屏蔽 SIGQUIT 并保存当前信号码
sigemptyset(&newmask);
sigaddset (&newmask, SIGQUIT);
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) {
perror("sigprocmask");
exit (EXIT_FAILURE);
}
sleep(8);
if (sigpending(&pendmask) < 0) {
perror("sigpending");
exit (EXIT_FAILURE);
}
if (sigismember(&pendmask, SIGQUIT))
printf ("\nSIGQUIT pending\n");
//取消对 SIGQUIT 的屏蔽
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) {
perror("sigprocmask");
exit (EXIT_FAILURE);
}
printf ("SIGQUIT unblocked\n");
sleep(10); //此处 SIGQUIT 信号生效,并生成 coredump 文件
exit (EXIT_FAILURE);
}
在上面程序中,首先使用 sigprocmask() 函数屏蔽了 SIGQUIT 信号 ,然后睡眠 8 秒。在这睡眠期间,可以利用 kill 命令连续向该程序发送多个 SIGQUIT 信号,但是这些信号都会被阻塞,而不递送到该进程。在 8 秒钟的睡眠醒来后,使用 sigpending() 和 sigismember() 两个函数检查 SIGQUIT 信号是否未决,自然,这肯定是未决的。接着,再使用 sigprocmask() 函数将 SIGQUIT 信号解除屏蔽(之前已经将旧的屏蔽字保存到 oldmask 中,此处还原) --- 需要注意此处的过程 --- 由于 SIGQUIT 信号现在已经不再受到阻塞,那么在 sigprocmask() 返回之前,之前的未决信号会被处理,因此会调用 sig_quit() 函数,完后,sigprocmask() 返回,再调用底下的 printf ("SIGQUIT unblocked\n"); 语句。接着继续睡眠 10 秒,由于不再对 SIGQUIT 信号屏蔽并且已经恢复了系统对该信号的默认处理,那么在此睡眠期间如果再发送一个 SIGQUIT 信号(可以通过 kill 命令,也可以在同一终端窗口里使用 Ctrl + \ 组合键),那么进程会产生 coredump 行为。上面藐视过程如下输出所示:[beyes@beyes signal]$ ./sigpending
My pid : 1336
SIGQUIT pending
caught SIGQUIT # 先处理未决信号,然后再从 sigprocmask() 返回
SIGQUIT unblocked
退出(吐核) #coredump,系统在中文语言环境下的翻译为吐核
上面注意到一个问题:之前使用 kill 命令发送了多个 SIGQUIT 信号,但只处理一次未决。这说明了这些多次发送的信号并没有被排队。这是因为,未决信号也只是一个掩码,它仅指示了信号是否发生过,但不会说明它到底发生了几次。换句话来说,如果在被屏蔽期间,相同的信号产生多次,这些行为都只会在信号集中标识为有这么一个信号未决,因此再最后解除屏蔽后递送出去时,只有一次。
当然,SIGQUIT 是标准信号,它并不支持信号排队,如果是实时信号,那么它们是支持信号排队的,也就是说,未决多少个,在解除屏蔽后就处理多少个。 |