信号集操作函数

控制原理:内核通过读取未决信号集来判断信号是否应被处理。信号屏蔽字mask可以影响未决信号集。而我们可以在应用程序中自定义set来改变mask。已达到屏蔽指定信号的目的。

更多函数具体使用 man *** 的方式查看手册 

信号集操作函数使用原理分析https://www.bilibili.com/video/BV1KE411q7ee/?p=134&spm_id_from=pageDriver&vd_source=d239c7cf48aa4f74eccfa736c3122e65

 信号集设定

sigset_t  set;                   

                                自定义信号集                        // typedef unsigned long sigset_t;

int sigemptyset(sigset_t *set);         

                                将某个信号集清0                        成功:0;失败:-1

int sigfillset(sigset_t *set);               

                                 将某个信号集置1                        成功:0;失败:-1

int sigaddset(sigset_t *set, int signum);         

                                将某个信号加入信号集                成功:0;     失败:-1

int sigdelset(sigset_t *set, int signum);           

                                将某个信号清出信号集                成功:0;失败:-1

int sigismember(const sigset_t *set, int signum);

                                判断某个信号是否在信号集中 

                                返回值:在集合:1;不在:0;出错:-1 

sigset_t类型的本质是位图。

                但不应该直接使用位操作,而应该使用上述函数,保证跨系统操作有效。

设置信号屏蔽字和解除信号屏蔽字

用来屏蔽信号解除屏蔽也使用该函数。其本质,读取或修改进程的信号屏蔽字(PCB 中)

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

        成功:0;失败:-1,设置 errno

        参数:

                set:自定义 set

                         传入参数,是一个位图,set中哪位置1,就表示当前进程屏蔽哪个信

                oldset:旧有的 mask

                        传出参数,保存旧的信号屏蔽集。

                how:

                        SIG_BLOCK:                                      设置阻塞

                        SIG_UNBLOCK:                                 取消阻塞

                        SIG_SETMASK:                                 用自定义 set 替换 mask

 查看未决信号集:

        int sigpending(sigset_t *set); 

                set:传出的  未决信号集

                返回值:成功:0;失败:-1,设置errno

案例一: 屏蔽ctrl+c信号,打印未决信号集

从结果可以很清楚的看出,当我们按下ctrl+c 未决信号机2号位置变成1,并且一直保持,就是因为我们利用·sigprocmask设置了阻塞信号集,信号无法递达。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<pthread.h>
#include<signal.h>

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}

void print_set(sigset_t *set) //打印操作 
{
    int i;
    for(i = 1; i < 32; i++)
    {
        if(sigismember(set, i)){ //利用成员判断函数
            putchar('1');
        } else {
            putchar('0');
        }
    }
    printf("\n");
}


int main(int argc, char *argv[])
{
    sigset_t set, oldset, pedset;

    int ret = 0;

    sigemptyset(&set);         // 清空
    sigaddset(&set, SIGINT);   //屏蔽 ctrl + c
    sigaddset(&set, SIGQUIT);  //屏蔽 ctrl + \
    sigaddset(&set, SIGBUS);   //屏蔽 总线
    sigaddset(&set, SIGKILL);  //屏蔽 kill   9号信号无法屏蔽

    //SIG_BLOCK 表示添加阻塞信号 set表示要覆盖的信号集 oldset表示旧的信号集
    ret = sigprocmask(SIG_BLOCK, &set, &oldset); //设置阻塞
    if(ret == -1){
        sys_err("sigprocmask error");
    }
    
    while(1)
    {
        ret = sigpending(&pedset);  //获取未决信号集 传出
        if(ret == -1){
            sys_err("sigpending error");
        }

         print_set(&pedset);  //打印 自定义的函数
         sleep(1);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43200943/article/details/129837178
今日推荐