UNIXC002 信号集、信号的阻塞

信号集,信号的阻塞

在这里插入图片描述

  • 未决信号: 未完成的信号,即信号产生了但是没有被处理。比如pending中的二三号信号。
  • 信号阻塞: 当信号到达以后,进程不对它做任何处理。比如blocking中搞得三四号信号。
  • 每个进程的PCB当中都维护这样两个数组,blocking和pending, 这是种特殊的数组,简称为信号集,每一位只能取值0或1.
  • handle代表对信号的处理, SIG_IGN: 忽略, SIG_DFL: 默认,user define: 自定义
  • 上图中:
    • 进程对一号信号不阻塞,但一号信号还没有发生(pending==0) 。 如果一号信号发生(pending==1), 待信号达时到进程将忽略它。
    • 进程对二号信号不阻塞,二号信号已经产生,但没有处理。待二号信号到达,进程会默认处理
    • 进程对三号信号阻塞,且三号信号已经发生但没处理,因为阻塞没有办法把信号抵达给进程。待三号信号阻塞解除,信号就可以抵达给进程,会使用用户自定义的函数进行处理。

1. 信号集

信号集类型 sigset_t 是结构体类型。一种类型,能够保存多个信号

typedef struct
  {
    unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))];
  } __sigset_t;
typedef __sigset_t sigset_t;

跟信号集类型相关的操作如下:

sigemptyset

在这里插入图片描述

sigfillset

在这里插入图片描述

sigaddset

在这里插入图片描述

  • set 需要已经初始化过的的具体的信号集

sigdelset

在这里插入图片描述

  • set 需要已经初始化过的的具体的信号集

sigismember

在这里插入图片描述

  • set 需要已经初始化过的的具体的信号集
#include <signal.h>
#include <stdio.h>
#define E_MSG(STRING, VAL) do{perror(STRING); return(VAL);}while(0)

int main(void){
    // 定义信号集类型变量set, 它是一个结构体类型
    sigset_t set;
    // 初始化信号集set为空
    sigemptyset(&set);
    // 将2,3号信号添加到信号集set中
    sigaddset(&set, 2);
    sigaddset(&set, 3);
    //测试3号信号是否为信号集中的一员
    int is = sigismember(&set, 3);
    if(is==-1)E_MSG("sigismember", -1);
    if(is)
        printf("signum 3 is member of set.\n");
    else
        printf("signum 3 is not member of set.\n");
    // 将3号信号从信号中移除
    sigdelset(&set, 3);
    is = sigismember(&set, 3);
    if(is==-1)E_MSG("sigismember", -1);
    if(is)
        printf("after del, signum 3 is member of set.\n");
    else
        printf("after del, signum 3 is not member of set.\n");
}
$ ./a.out 
signum 3 is member of set.
after del, signum 3 is not member of set.

2. 信号的阻塞

sigprocmask

在这里插入图片描述
在这里插入图片描述

  • 因为没有const,oldset 信号集里的内容有可能会被改变
  • 信号掩码集就是阻塞信号集, 用来屏蔽掉信号集中为1 的信号
  • ctrl c 是2号信号,ctrl \ 是3号信号, 可以被阻塞,但是9号信号今天的这例子中没有办法被阻塞
  • 信号的阻塞是信号不会被递送给进程,信号忽略是信号已经递送达到,进程对信号的处理方式是忽略
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

#define E_MSG(STRING, VAL) do{perror(STRING); return(VAL);}while(0)

void handle(int n){
    printf("rev...%d\n", n);
}
int main(void){
    // 阻塞解除以后,调用handle来处理信号
    signal(2, handle);
    signal(3, handle);
    // 定义信号集类型的变量
    sigset_t set, oldset;
    // 初始化信号集set为空
    sigemptyset(&set);
    // 将2, 3, 9信号设置为进程信号的掩码集
    sigaddset(&set, 2);
    sigaddset(&set, 3);
    sigaddset(&set, 9); // 即使这里阻塞了9号信号,用kill -9 pid 也还是能杀死这个进程
    // 将信号集set设置为进程的信号掩码集, 并把之前的信号集保存到oldset
    int sm = sigprocmask(SIG_SETMASK,&set, &oldset);
    if(sm == -1)E_MSG("sigprocmask", -1);
    sleep(5);
    // 恢复原来的信号掩码集
    sm = sigprocmask(SIG_SETMASK, &oldset, NULL);
    if(sm == -1)E_MSG("sigprocmask", -1);
    while(1);

    return 0;
}
$ ./a.out
# 5s内发送多次2号信号和3号信号,会被阻塞 
^C^C^C^\^\ ^\ 
# 5s后,恢复原来的信号掩码集不再阻塞2,3号信号
# 进程将会收到刚刚的2号和3号信号,但只会收到一次(2,3 都是不可靠信号)会有信号丢失
# 然后用handle函数来处理
rev...3
rev...2
# 然后再发送2, 3号信号给进程,都不再会被阻塞
^Crev...2
^Crev...2
^\rev...3
^\rev...3
  • kill -9 这个进程也是能杀掉的,据说9号进程是穿甲弹
  • 不可靠信号有信号的丢失,可靠信号没有信号的丢失。从1到31都是不可靠信号,34到64都是可靠信号。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值