曲径通幽论坛

标题: sigpending() -- 返回未决信号 [打印本页]

作者: beyes    时间: 2012-8-2 12:59
标题: sigpending() -- 返回未决信号
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 是标准信号,它并不支持信号排队,如果是实时信号,那么它们是支持信号排队的,也就是说,未决多少个,在解除屏蔽后就处理多少个。
作者: xin2893    时间: 2013-7-8 10:33
这象一个函数大全,有例子,有解释,真是用心了




欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2