LINUX系统编程:信号(2)

目录

2.信号的保存

2.1信号保存的基本概念

2.2信号在哪里保存的?怎么保存的?

2.3处理信号的三张表

2.4三张表的匹配操作和系统调用接口

2.4.1sigprocmask

2.4.2sigemptyset

2.4.3sigfillset

2.4.4sigaddset&&sigdelset

2.4.5sigismember

2.4.6sigpending

2.5demo代码

细节


2.信号的保存

2.1信号保存的基本概念

处理信号的动作叫做递达(Delivery),处理信号有三种方式,默认,忽略,自定义。

信号从产生到信号递达之间的状态叫做未决(Pending)。

进程可以选择阻塞(Block)某个信号。

2.2信号在哪里保存的?怎么保存的?

信号是在进程pcb中被保存的,也就是task_struct中。

保存的方式采用的是位图。

struct
{
    unsigned long int pending;
    unsigned long int block;
};

pending:比特位的位置表示信号的编号,比特位的内容表示是否是未决的。

block:比特位的位置表示信号的编号,比特位的内容表示是否是阻塞。

阻塞和忽略不是一个概念

阻塞是阻止信号递达,忽略是递达之后忽略。

2.3处理信号的三张表

block就是block位图,pending就是pending位图,handler是一个函数指针数组。

当进程收到2信号,首先会将pending位图第二比特位变为1,等到机会合适时处理pending中的信号,处理时会看2号信号的位置在block中是否为1,如果为1就阻塞住,不递达,为0就递达,调用handler中对应的函数。

2.4三张表的匹配操作和系统调用接口

2.4.1sigprocmask

查看和修改阻塞信号,就是修改block位图。

how:如何修改

set:信号集

sigset_t类型是一个结构体,__val就是和pending一样的位图。

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

oldset:输出型参数,将未修改之前的位图保存。

返回值

成功返回0,失败返回-1

2.4.2sigemptyset

将参数set初始化,并把所有信号都清空。

2.4.3sigfillset

将set初始化,包含所有信号。

2.4.4sigaddset&&sigdelset

向set信号集中添加或者删除信号,参数signum就是添加几号信号。

2.4.5sigismember

检查set信号集中是否包含signum

包含返回1,不包含返回0,出错返回-1.

2.4.6sigpending

检查pending位图

set是输出型参数。

2.5demo代码

1.屏蔽2号信号

2.打印pending位图中的内容

3.向进程发送2号信号,因为2号信号被阻塞了,所以2号信号会一直在pending位图中。

#include<iostream>
#include<signal.h>
#include<string.h>
#include<cerrno>

void print(sigset_t* s)
{
    for(int i = 31; i > 0; i--)
    {
        if(sigismember(s,i) == 1)
        {
            std::cout<<"1";
        }
        else if(sigismember(s,i) == 0)
        {
            std::cout<<"0";
        }
        else
        {
            std::cout<<"sigismember fail:"<<strerror(errno)<<std::endl;
        }
    }
    std::cout<<std::endl;
}

int main()
{   
    sigset_t s;
    sigset_t output;
    sigemptyset(&s);
    sigaddset(&s,2);
    sigprocmask(SIG_SETMASK,&s,&output);
    sigset_t pend;
    while(true)
    {
        sigpending(&pend);
        print(&pend);
        sleep(1);
    }
    return 0;
}

 使用kill命令向进程sigPreserve发送2号信号

pending位图的2号信号位置果然变为1了。

那是不是这个进程把所有的信号都屏蔽了,那这个进程是不是就无敌了我们可以试验一下。

直接将所有信号阻塞,看有没有信号可以杀死该进程。

我们发现,1-8号都成功的被阻塞了,但是9号信号直接杀死了进程。

SIGKILL (9):这是一个强制终止进程的信号,通常由系统管理员或者操作系统自身发送。它无法被阻塞,因为它的目的是强制终止进程,即使进程已经阻塞了所有其他信号。

SIGSTOP (19) 和 SIGCONT (18):SIGSTOP 用于暂停进程的执行,SIGCONT 用于继续执行被暂停的进程。它们也是不可阻塞的,因为它们是用来控制进程执行状态的信号,不受进程阻塞的影响。

细节

1.信号被递达的时候一定会把对应的pending位图清空。

2.先清空pending位图,再递达

  • 29
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值