Linux信号之信号的保存

news2025/1/4 19:36:48

(。・∀・)ノ゙嗨!你好这里是ky233的主页:这里是ky233的主页,欢迎光临~icon-default.png?t=N7T8https://blog.csdn.net/ky233?type=blog

点个关注不迷路⌯'▾'⌯

目录

一、阻塞信号

1.信号递达、未决、阻塞

 2.内核表示图

3.sigset_t

4.sigpending

5.sigprocmask

二、验证问题

1.问题一

2.问题二

3.问题三


一、阻塞信号

1.信号递达、未决、阻塞

  • 实际执行信号的处理动作称为信号递达(Delivery)。

  • 信号从产生到递达之间的状态,称为信号未决(Pending)。
  • 进程可以选择阻塞 (Block )某个信号。
  • 被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。
  • 注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。

 2.内核表示图

在内核中其实一共有两个位图结构,第二个就是我们的pending位图,也就是OS修改的位图结构,第三个则是代表的信号,是一个函数指针数组,里边存放的是所对应的函数地址

而在handler里面会先判断是否是等0还是1,0则执行默认的动作,1则直接忽略的动作,都不是才会执行我们自己写的动作!

第一个block则代表的是我们的阻塞位图,OS先把对应的信号写入pending里,然后回来查看,block里面是否阻塞,如果阻塞则不进行调用,等到不阻塞时候才回去handler里进行下一步操作!

3.sigset_t

这是一个位图结构,但是不允许用户自己进行位操作,所以OS给我们提供了对应的操作方法

用户可以直接使用该类型,和用内置类型以及自定义类型是没有任何差别的 

每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。 因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号 的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有 效”和“无效”的含义是该信号是否处于未决状态。

总的来说就是用来表示block和pending的

int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset (sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo); 

上面就是OS所提供的五个可以对位图本身修改的接口

  1. 函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含 任何有 效信号。
  2. 函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示 该信号集的有效信号包括系 统支持的所有信号。
  3. 注意,在使用sigset_ t类型的变量之前,一定要调 用sigemptyset或sigfillset做初始化,使信号集处于确定的 状态。初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效信号
  4. sigismember:最后一个是判定一个信号时候再该信号集之中 

4.sigpending

int sigpending(sigset_t *set)

通过该函数可以获取当前调用进程的pending信号集,也就是把操作系统内核中的数据拿给用户

  • 返回值:成功为0,失败为-1

5.sigprocmask

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

检查并更改我们的阻塞信号集

  • 参数一:设定特定的操作
  • 参数二:设定特定的位图
  • 参数三:输出型参数,返回老的信号屏蔽图(阻塞位图block),如果需要的话
  • 返回值:若成功则为0,若出错则为-1

how:

  • SIG_BLOCK:set包含了我们希望添加到当前信号屏蔽字的信号,相当于mask=mask|set
  • SIG_UNBLOCK:set包含了我们希望从当前信号屏蔽字中解除阻塞的信号,相当于mask=mask&~set
  • SIG_SETMASK:设置当前信号屏蔽字为set所指向的值,相当于mask=set

二、验证问题

1.问题一

如果我们对所有的信号都进行了自定义不做,我们是不是就写了一个不会被一场或者用户杀掉的进程?

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

void catchSig(int signum)
{
    cout << "获得了一个信号:" << signum << endl;
}

int main()
{
    for (int i = 1; i <= 31; i++)
    {
        signal(i, catchSig);
    }
    while (1)
    {
        sleep(1);
    }
    return 0;
}

 虽然我们看到的好像就是这样,可其实并不是,OS设计者也考虑过,我们的9号信号(SIGKILL)是不可以被捕捉的!

2.问题二

如果我们将二号信号阻塞,并且不断地获取并打印当前进程的pending信号,如果我们突然发送一个二号信号,我们应该肉眼看到pending信号集中,有一个比特位从0变为1

static void shouPending(sigset_t &pending)
{
    for (int sig = 1; sig <= 31; sig++)
    {
        if (sigismember(&pending, sig))
        {
            cout << "1";
        }
        else
        {
            cout << "0";
        }
    }
    cout << endl;
}

int main()
{
    // 定义信号集
    sigset_t bset, obset;
    sigset_t pending;
    // 初始化
    sigemptyset(&bset);
    sigemptyset(&obset);
    sigemptyset(&pending);
    // 添加要进行屏蔽的信号
    sigaddset(&bset, 2);
    // 设置set到内核中
    int n = sigprocmask(SIG_BLOCK, &bset, &obset);
    assert(n == 0);
    cout << "2号信号以阻塞" << endl;
    (void)n;
    // 重复打印当前的pending信号集
    while (1)
    {
        // 获取当前进程的pending信号集
        sigpending(&pending);
        // 显示pending中的没有被递达的信号
        shouPending(pending);
        sleep(1);

    }
    return 0;
}

首先我们看到当前进程的pending位图都是0,这是因为虽然我们阻塞了,但是不代表这个进程收到了2号信号,当我们发完之后,确实如我们所说,有一个比特位由0变1了

 可是如果我们要解除2号信号的阻塞呢?那我们的pending信号集就应该从1变成0!

#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <assert.h>
using namespace std;

static void shouPending(sigset_t &pending)
{
    for (int sig = 1; sig <= 31; sig++)
    {
        if (sigismember(&pending, sig))
        {
            cout << "1";
        }
        else
        {
            cout << "0";
        }
    }
    cout << endl;
}

int main()
{
    // 定义信号集
    sigset_t bset, obset;
    sigset_t pending;
    // 初始化
    sigemptyset(&bset);
    sigemptyset(&obset);
    sigemptyset(&pending);
    // 添加要进行屏蔽的信号
    sigaddset(&bset, 2);
    // 设置set到内核中
    int n = sigprocmask(SIG_BLOCK, &bset, &obset);
    assert(n == 0);
    cout << "2号信号以阻塞" << endl;
    (void)n;
    // 重复打印当前的pending信号集
    int count = 0;
    while (1)
    {
        // 获取当前进程的pending信号集
        sigpending(&pending);
        // 显示pending中的没有被递达的信号
        shouPending(pending);
        sleep(2);
        count++;
        if (count == 10)
        {
            int n = sigprocmask(SIG_SETMASK, &obset, nullptr);
            assert(n == 0);
            (void)n;
            cout << "解除2号信号的阻塞" << endl;

        }
    }
    return 0;
}

可是我们并没有看到从1到0,这是因为进程直接终止了,在默认情况下,解除阻塞2号信号直接递达了,需要捕捉一下!

static void shouPending(sigset_t &pending)
{
    for (int sig = 1; sig <= 31; sig++)
    {
        if (sigismember(&pending, sig))
        {
            cout << "1";
        }
        else
        {
            cout << "0";
        }
    }
    cout << endl;
}

static void handler(int signum)
{
    cout<<"捕捉信号:"<<signum<<endl;
}
int main()
{
    //测试捕捉
    signal(2,handler);
    // 定义信号集
    sigset_t bset, obset;
    sigset_t pending;
    // 初始化
    sigemptyset(&bset);
    sigemptyset(&obset);
    sigemptyset(&pending);
    // 添加要进行屏蔽的信号
    sigaddset(&bset, 2);
    // 设置set到内核中
    int n = sigprocmask(SIG_BLOCK, &bset, &obset);
    assert(n == 0);
    cout << "2号信号以阻塞" << endl;
    (void)n;
    // 重复打印当前的pending信号集
    int count = 0;
    while (1)
    {
        // 获取当前进程的pending信号集
        sigpending(&pending);
        // 显示pending中的没有被递达的信号
        shouPending(pending);
        sleep(2);
        count++;
        if (count == 10)
        {
            int n = sigprocmask(SIG_SETMASK, &obset, nullptr);
            assert(n == 0);
            (void)n;
            cout << "解除2号信号的阻塞" << endl;

        }
    }
    return 0;
}

这时我们就看到了当前进程的pending信号集从1变成了0!

还有一个小问题,貌似没有一个接口用来设置我们的pending位图,这是因为我们的所有发送信号的方式,都是修改pending位图的过程

3.问题三

如果我们对所有的信号都阻塞,我们是不是就写了一个不会被一场或者用户杀掉的进程?

static void shouPending(sigset_t &pending)
{
    for (int sig = 1; sig <= 31; sig++)
    {
        if (sigismember(&pending, sig))
        {
            cout << "1";
        }
        else
        {
            cout << "0";
        }
    }
    cout << endl;
}


static void blockSig(int signum)
{
    sigset_t bset;
    sigemptyset(&bset);
    sigaddset(&bset, signum);
    int n = sigprocmask(SIG_BLOCK, &bset, nullptr);
    assert(n == 0);
    (void)n;
}
int main()
{
    for(int sig=1;sig<=31;sig++)
    {
        blockSig(sig);
    }
    sigset_t pending;
    while(1)
    {
        sigpending(&pending);
        shouPending(pending);
        sleep(1);
    }
    return 0;
}

和第一个问题是一样的,9号信号同样也不可以被阻塞!

同样的还有我们的19号暂停命令和20号命令!

所以最终结论,无论是9号信号就不可被捕捉和屏蔽的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1388737.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

yolov1:背景介绍与算法精讲

目录 一、背景介绍1.1 yolo发展历史1.2 作者介绍 二、算法精讲2.1 预测阶段2.2 训练阶段 三、论文细节 一、背景介绍 其实在写这篇博客的时候yolov1~yolov8的所有网络结构以及算法思想和源码都已经研究很久了&#xff0c;回过头继续读v1会发现有很多细节是自己没有留意的&#…

Linux上新部署的项目jar包没有生效

今天公司新安排了一个项目&#xff0c;这里简称项目A&#xff0c;需要新增两个功能&#xff0c;我这边完成之后&#xff0c;跟前端对接好了&#xff0c;调试也没有问题。 然后把项目打包上传到测试服务器上&#xff0c;重新启动项目&#xff0c;发现项目A新增的接口没有生效&a…

多变量线性回归

一、多维特征 目前为止&#xff0c;我们探讨了单变量/特征的回归模型&#xff0c;现在我们对房价模型增加更多的特征&#xff0c;例如房间数、楼层等&#xff0c;构成一个含有多个变量的模型&#xff0c;模型中的特征为。 增添更多特征后&#xff0c;我们引入一系列新的注释&am…

【数据结构和算法】奇偶链表

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 方法一&#xff1a;分离节点后合并 三、代码 3.1 方法一&#xff1a;分离节点后合并 四、复杂度分…

shopee、Lazada、速卖通测评自养号技术,当天注册当天直接下单

自养号测评&#xff08;补单&#xff09;技术对跨境平台如shopee、Lazada、速卖通、ebay、wish、mercari、Newegg等是否有用&#xff1f; 随着越来越多的跨境电商进入市场&#xff0c;并且考虑到亚马逊对大卖家的严格监管&#xff0c;这无疑为其他跨境电商平台和独立站市场带来…

Smallpdf扫描、转换、压缩、编辑、签名PDF

【应用名称】&#xff1a;Smallpdf: 扫描、转换、压缩、编辑、签名PDF 【适用平台】&#xff1a;#Android 【软件标签】&#xff1a;#Smallpdf 【应用版本】&#xff1a;1.71.0 【应用大小】&#xff1a;150MB 【软件说明】&#xff1a;通过 Smallpdf&#xff0c;您可以&…

6.3.1认识Camtasia4(1)

6.3.1认识Camtasia4 安装完Camtasia4(本书使用Camtasia4.0.1版本)后&#xff0c;单击【开始】|【程序】|【Camtasia Studio 4】|【Camtasia Studio】&#xff0c;启动Camtasia Studio&#xff0c;启动后界面如图6-3-1所示。 图6-3-1 Camtasia Studio界面 Camtasia Studio窗口中…

编程笔记 html5cssjs 040 CSS盒子模型

编程笔记 html5&css&js 040 CSS盒子模型 一、CSS 盒子模型二、元素的宽度和高度三、最终元素的总宽度四、元素的总高度五、练习小结 网页是靠分成不同的块&#xff0c;再赋予这些块各不相同的属性来布局的。所以这个“块”是一个基础。先看块本身的构造。 一、CSS 盒子…

shell 循环 判断

for 循环 Shell 脚本里最简单的循环当属 for 循环。最简单的 for 循环如下所示&#xff0c;你只需将变量值依次写在 in 后面即可&#xff1a; #!/bin/bashfor num in 1 2 3 4 doecho $num done 如果要循环的内容是字母表里的连续字母或连续数字&#xff0c;那么就可以按以下语…

医院住院综合服务管理系统

&#x1f345;点赞收藏关注 → 私信领取本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345;一 、设计说明 1.1 课题背景 互…

大模型理论基础1

大模型理论基础1 第一章&#xff1a;引言 语言模型 自回归语言模型 概率的链式法则&#xff1a; 在自回归语言模型 p 中生成整个序列 X1:L&#xff0c;我们需要一次生成一个令牌(token)&#xff0c;该令牌基于之前以生成的令牌进行计算获得&#xff1a; 其中T≥0 是一个控…

OLAP引擎也能实现高性能向量检索,据说QPS高于milvus!

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 随着 LLM 技术应用及落地&#xff0c;数据库需要提高向量分析以及 AI 支持能力&#xff0c;向量数据库及向量检索等能力“异军突起”&#xff0c;迎来业界持续不断关…

C 程序运行机制

1.编辑 编写C语言源程序代码&#xff0c;源程序文件以“.c”作为扩展名。 2.编译 将C语言源程序转换为目标程序(或目标文件)。如果程序没有错误&#xff0c;没有任何提示&#xff0c;就会生成一个扩展名为“.obj”的二进制文件。C语言中的每条可执行语句经过编译后最终都将被…

深入探索CSS动画的魅力-附带动画实例

一、网页动画发展简史 GIF动画 GIF全称为“Graphics Interchange Format”&#xff0c;是一种基于LZW算法的连续色调无损压缩格式。 由于其文件小、无损压缩、易于播放等优点&#xff0c;GIF成为了网页动画的最初选择。然而&#xff0c;GIF动画的色彩数量和帧数有限&#xff…

YOLOv5姿态估计:HRnet实时检测人体关键点

前言&#xff1a; Hello大家好&#xff0c;我是Dream。 今天来学习一下利用YOLOv5进行姿态估计&#xff0c;HRnet与SimDR检测图片、视频以及摄像头中的人体关键点&#xff0c;欢迎大家一起前来探讨学习~ 本文目录&#xff1a; 一、项目准备1Pycharm中克隆github上的项目2.具体步…

森林消防泵:及时扑灭林火,保护森林生态平衡

在大自然中&#xff0c;森林是我们宝贵的自然资源&#xff0c;它们为我们提供氧气、净化空气、保持水土&#xff0c;还是许多动植物的家园。然而&#xff0c;森林火灾却时常威胁着这片绿色宝地的安全。为了保护森林生态环境&#xff0c;我们需要及时扑灭林火。而恒峰智慧科技研…

PhotoMaker, 腾讯开源人像图形处理

腾讯于昨天开源一款人像图形处理项目&#xff0c;项目地址&#xff1a;github.com/TencentARC/PhotoMaker 项目演示地址&#xff1a;https://huggingface.co/spaces/TencentARC/PhotoMakerhttps://huggingface.co/spaces/TencentARC/PhotoMaker-Style 演示效果&#xff1a; 项…

48-DOM

1.DOM基础 Document Object Module,文档对象模型,window对象,document文档,都可以获取和操作 1)文档节点 2)属性节点(标签内的属性href,src) 3)文本节点(标签内的文字) 4)注释节点 5)元素节点(标签) 2.获取元素节点 2.1通过标签名获取 <p>1</p><…

数字图像处理常用算法的原理和代码实现详解

本专栏详细地分析了常用图像处理算法的数学原理、实现步骤。配有matlab或C实现代码&#xff0c;并对代码进行了详细的注释。最后&#xff0c;对算法的效果进行了测试。相信通过这个专栏&#xff0c;你可以对这些算法的原理及实现有深入的理解&#xff01;   如有疑问&#xf…

在window宿主机访问WSL2内部署的服务

目录 在window宿主机访问 WSL2 内部署的服务&#xff08;其他&#xff09;在 WSL2 内查看 windows&#xff08;宿主机&#xff09;的IP地址 windows内置了Linux系统&#xff08;WSL&#xff09;。 在window宿主机访问 WSL2 内部署的服务 在WSL下部署的项目&#xff0c;比如端口…