曲径通幽论坛

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

[信号] sigprocmask() -- 设置当前信号屏蔽

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2012-8-1 19:32:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
sigprocmask() 函数原型如下:
[C++] 纯文本查看 复制代码
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

该函数用来设置当前信号屏蔽,也就是说,通过该函数可以设置你想要屏蔽的信号,即被屏蔽的信号递送过来,不给予理会。函数有 3 个参数,第 3 个参数 oldset 如果是个非空指针,那么进程的当前信号屏蔽字就通过 oldset 返回,或者说在设置新的信号屏蔽字之前,我们想备份一下原来的信号集设置,那么备份方法就是指定该参数。

第 2 个参数如果是个非空指针,那么它就会依照第 1 个参数 how 的指示来修改当前的信号屏蔽字,how 有 3 种方式:

1. SIG_BLOCK
该进程新的信号屏蔽字是当前信号屏蔽字和 set 指向信号集的并集,也就是说 set 包含了我们希望阻塞的附加信号。

2. SIG_UNBLOCK
该进程的新的信号屏蔽字是当前信号屏蔽字和 set 所指向的信号集补集的交集,也就是说 set 包含了我们希望解除阻塞的信号。

3. SIG_SETMASK
该进程新的信号屏蔽字将被 set 指向的信号集的值所替代。

如果 set 是个空指针,那么不改变该进程的信号屏蔽字,而 how 的值也因此无意义。

需要注意的是,SIGKILL (9号信号)和 SIGSTOP (19号信号)不能被屏蔽,如果这样,那么该进程没法杀死,成为一个霸道进程,这是不允许的。

测试代码:
[C++] 纯文本查看 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

char *pname;
static volatile sig_atomic_t got_sig_int = 0;

static void handler(int sig)
{
    if (sig == SIGUSR1)
       got_sig_int = 1;
    else
       printf ("%s: signal %d caught\n", pname, sig);
}

int main(int argc, char *argv[])
{
    int n;
    pname = argv[0];
    
    printf ("my pid : %d\n", (long)getpid());    

    sigset_t block_mask;
    
    for (n = 1; n < NSIG; n++)      //所有的信号都使用同一个处理函数
            (void)signal(n, handler);   //忽略错误(SIGKILL 和 SIGSTOP 不会被安装)


    sigfillset(&block_mask);        // 屏蔽所有信号,除了 SIGKILL 和 SIGSTOP
    sigprocmask(SIG_SETMASK, &block_mask, NULL);
    
    sigset_t unblock_mask;

    sigemptyset (&unblock_mask);
    sigaddset (&unblock_mask, SIGUSR1); 
    if (sigprocmask(SIG_UNBLOCK, &unblock_mask, NULL) == -1) {     //不屏蔽第 10 号信号
              perror("sigprocmask");
              exit (EXIT_FAILURE);
        }



    while(!got_sig_int)        //等待第 10 号信号
         continue;

    printf("signal SIGUSER1 caught.\n");

    return 0;
}

在一个终端窗口里运行该程序:
[beyes@beyes   signal]$ ./sigprocmask
my pid : 2421
接着,可以在另外一个终端窗口里用 kill 命令给该程序发送信号:
[beyes@beyes   ~]$ kill -1 2421        
[beyes@beyes   ~]$ kill -2 2421
[beyes@beyes   ~]$ kill -10 2421
在上面发送第 1 和第 2 号信号时,程序不会有任何反应。但是当发送第 10 号信号时,程序就会退出,此时可以看到:
signal SIGUSER1 caught.
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-5-29 06:53 , Processed in 0.097137 second(s), 24 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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