Linux-信号保存

server/2024/11/25 19:34:43/

1. 概念

        进程执行信号的处理动作,称为 信号递达(Delivery)

        信号从产生到递达之间的状态,称为 信号未决(Pending)

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

过程:

        信号产生 —— 信号未决 —— (是否阻塞)—— 信号递达

        信号在未决状态,其实就是信号保存在进程PCB内

阻塞和忽略的区别:

        忽略是一种信号的处理动作,在信号递达时才会体现;而阻塞,信号根本就不会递达

        那么信号是如何保存在进程PCB(task_struct)中的呢? 

2. 内核结构

        内核中task_struct的会有三个指针指向三个位图

         由pending位图决定信号是否产生,被保存;block位图决定信号是否被阻塞,handler位图决定信号被抵达时的处理动作

        其中__sighandler_t类型是函数指针,void handler(int ),函数参数为int类型,返回值为void类型,其中SIG_DEF(默认)和SIG_IGN(忽略)是宏定义,分别表示__sighandler_t类型强转的0和1

        当信号的默认处理动作为默认时,它会去调用对应的信号默认处理动作

信号处理流程:

        

3. 函数接口

        默认情况下,阻塞block位图为全0,用户可以修改

        OS提供自定义类型 sigset_t 和对应的操作该位图的方法,用户需要用这些方法和接口才能修改 sigset_t 类型的位图。用户想要修改block阻塞位图就必须利用 sigset_t 作为系统调用接口的参数。

        sigset_t 被称为 信号集;block位图,被称为 阻塞信号集 或者 信号屏蔽字(signal mask)

修改信号集的接口

  • sigemptyset:初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含任何有效信号
  •  函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示该信号集的有效信号包括系统支持的所有信号
  • 初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效信号
  • sigismember:确定 signum 信号对应的位置是否为1 返回值:真1,否0,出错-1

注意: 在使用sigset_ t类型的变量之前,一定要调用sigemptyset或sigfillset做初始化,使信号集处于确定的状态

读取或更改进程的信号屏蔽字:

set:

        若set为空指针,读取进程当前的信号屏蔽字,oldset传出

        若set为非空,根据how指示,通过set修改信号屏蔽字,原先的通过oldset(若为非空)传出

how:

SIG_BLOCKmask = mask | set添加
SIG_UNBLOCKmask = mask & ~set解除
SIG_SETMASKmask = mask覆盖
        如果调用sigprocmask解除了对当前若干个未决信号的阻塞,则在函数返回前,至少将其中一个信号递达(在下一篇博客中解答为什么)

读取当前进程的未决信号集:

        读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1

通过这些接口做的小实验:

#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <assert.h>
using namespace std;void handler(int sig)
{cout << "捕获signal:" << sig << endl;
}void Print(const sigset_t& set)
{for(int i = 1; i <= 31; ++i){if(sigismember(&set, i) == 1)cout << 1;else    cout << 0;}cout << endl;  
}int main()
{for(int i = 1; i <= 31; ++i){signal(i, handler);}sigset_t set;sigfillset(&set);sigprocmask(SIG_SETMASK, &set, nullptr);while(true){sigset_t oset;sigemptyset(&oset);sigpending(&oset);Print(oset);sleep(1);}return 0;
}
i=1
id=$(pidof mysignal)
while [ $i -le 31 ]
doif [ $i -eq 9 ];thenlet i++continuefiif [ $i -eq 19 ];thenlet i++continuefikill -$i $idecho "kill -$i $id"let i++sleep 1
done

完。 


http://www.ppmy.cn/server/38324.html

相关文章

盘点一下4种常见的微信的广告类型,在微信上打广告要花多少钱?

微信是一款社交媒体应用&#xff0c;集Facebook、Instagram和Snapchat的功能于一身。该应用拥有超过12亿的月活跃用户&#xff0c;其中约7亿为日活跃用户。由于其在中国网民中的成功和广泛的通信工具&#xff0c;微信是推广您业务的绝佳平台。 在这篇博客文章中&#xff0c;我…

qt day 3

优化登录框&#xff0c;点击登录按钮&#xff0c;如果账号和密码匹配&#xff0c;则弹出 信息对话框 给出提示信息“登录成功”&#xff0c;并给出一个 ok 按钮&#xff0c;当用户点击 ok 后&#xff0c;关闭当前界面&#xff0c;跳转到另一个界面&#xff1b;如果账号和密码不…

前端css中径向渐变(radial-gradient)的使用

前端css中径向渐变的使用 一、前言二、主要内容说明&#xff08;一&#xff09;、径向渐变的形状1.椭圆形渐变&#xff08;ellipse&#xff09;&#xff0c;源码12.源码1运行效果3.圆形渐变&#xff08;circle&#xff09;&#xff0c;源码24.源码2运行效果 &#xff08;二&…

通义千问-7B-Chat-Int4

通义千问-7B-Chat-Int4 代码仓库地址&#xff1a;https://github.com/QwenLM/Qwen 安装 克隆我们的仓库并跳转到相应目录 git clone https://www.modelscope.cn/qwen/Qwen-7B-Chat-Int4.git cd Qwen-7B-Chat-Int4 2. 创建 conda 环境 conda create -n qwenint4 python3.8…

快速排序应用

题目描述 著名的快速排序算法里有一个经典的划分过程:通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。 给定一个划分后的正整数序列,请问有多少个元素可能是划分过程中选取的主元? 并按升序输出这些主元。 解…

4. 寻找两个正序数组的中位数

题目描述 2个有序数组&#xff08;保证不能同时为空&#xff09;长度分别为m&#xff0c;n&#xff1b;求他们的中位数。 要求时间复杂度O(long(mn))。 解题思路 题目的要求可以转述为求第k大个数&#xff0c;k可能为1个数&#xff0c;可能为2个数。 k(mn)/2 num1[k/2]表示…

vue 脚手架 创建vue3项目

1、nodeJS下载地址&#xff1a;下载 Node.js 2、安装 nodeJS 打开cmd窗口检查是否安装成功&#xff1a;node -v&#xff08;如果显示出了版本号&#xff0c;那么说明安装成功了&#xff09; 设置阿里云镜像&#xff1a;npm config set registry https://registry.npmmirror.co…

苍穹外卖总结

1 软件开发流程 需求分析->设计->编码->单元测试->集成测试->上线运维 1.1 需求分析 交付结果&#xff1a;完成需求规格说明书、产品原型 需求规格说明书&#xff1a;系统定义、应用环境、功能规格、性能需求 产品原型&#xff1a;一般通过网页的形式展示当…