波奇学Linux:信号的发送和保存

信号的发送的对象是pcb

task_struct{
int signal; //0000 0000 .... 0001

进程pcb中存在int型的signal来保存信号,用位图的方式,比特位的0,1表示是否收到信号

比特位位置表示信号的编号。

 发信号的本质就是修改task_struct的信号位图对应的比特位。

信号的作用是为了给用户层传递信息

信号的保存的原因:进程收到信号不会立即处理这个信号,要有个时间窗口

实时信号:立即处理,不能丢失

信号的保存

信号递达,信号未决,信号阻塞

信号递达(delivery):实际执行信号的处理的动作,即执行。

信号未决(pedding):信号从产生到递达之间的状态,就是把修改对应比特位,即信号传到进程。

进程可以选择阻塞(Block)某个信号,被阻塞的信号将处于pending状态,解除阻塞才进入递达状态。

忽略是递达后的状态和block不一样,忽略和自定义,默认是递达后三种处理方法

用户提供的方法可以覆盖handler数组的自定义方法

信号集类型sigset_t:封装好的位图

sigemptyset():初始化,并类图所有项都为0

sigaddset(sigset_t*set, int signum) 将位图的第signum位设为1

函数sigprocmask读取或者更改进程的信号屏蔽字。

修改当前进程的block位图

how的选项是

SIG_BLOCK:取位图交集

SIG_UNBLOCK:最后的set的block是参数set和old set共有的

SIG_SETMASK :覆盖

set:是新的位图

oldset是系统的位图

接口实操代码

#include<iostream>
#include<signal.h>
#include<unistd.h>

using namespace std;

void PrintPending(sigset_t &pending)
{
    for(int signo=1;signo<=31;signo++)
    {
        if(sigismember(&pending,signo))
        {
            cout<<"1";
        }
        else
        {
            cout<<"0";
        }
    }
    cout<<endl;
    
}
void handler(int signo)
{
    cout<<"catch a signo: "<<signo<<endl;
}

int main()
{
    signal(2,handler);
   //对栈上的位图进行操作
    sigset_t bset,oset; //封装好的类图
    sigemptyset(&bset); //初始化类图
    sigaddset(&bset,2); //修改本地的类图
    //对阻塞的位图进行操作
    sigprocmask(SIG_SETMASK,&bset,&oset);
    sigset_t pending;
    int cnt=0;
    while(true)
    {
        int n=sigpending(&pending); //获取pending类图
        if(n<0)continue;
        PrintPending(pending);
        sleep(1);
        cnt++;
        if(cnt==20)
        {
            cout<<"unblock 2 signo"<<endl;
            sigprocmask(SIG_SETMASK,&oset,nullptr);
        }
    }
    // 打印pending
    // 发送2号信号 000...010

    return 0;
} 

利用mask可以把所有信号进程屏蔽,信号不就不会被处理。

信号捕捉处理

当我们的进程从内核态回到用户态进行信号的检测和处理

当系统调用时,操作系统会做身份切换的,用户身份变成内核身份,或者反着来

int 80 从用户态变成内核态

内核态:允许访问自己的系统代码和数据。

系统调用就是在1GB的地址空间进行执行的

操作系统视角:任何一个时刻,都会有进程执行,执行操作系统的代码就可以随时执行

操作系统的本质:基于时间中断的死循环,有一个时钟芯片,发送时间中断,驱动操作系统进行调度。

ecs寄存器有两个标志比特位 00 表示内核态,用户态是11,当切换到内核态时,才能访问内核代码。int 80陷入80

do_signal()检测信号

进入到用户态执行方法,如果是系统方法,再进行系统态。

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值