曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 4707|回复: 1
打印 上一主题 下一主题

[信号] sigpending() -- 返回未决信号

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2012-8-2 12:59:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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 是标准信号,它并不支持信号排队,如果是实时信号,那么它们是支持信号排队的,也就是说,未决多少个,在解除屏蔽后就处理多少个。

0

主题

1

帖子

0

积分

初学弟子

积分
0
沙发
发表于 2013-7-8 10:33:32 | 只看该作者
这象一个函数大全,有例子,有解释,真是用心了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-4 00:03 , Processed in 0.128359 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表