Linux 进程间的信号

news2024/11/19 6:33:19

1.信号的初认识

        信号是进程之间事件异步通知的一种方式,属于软中断。通俗来说信号就是让用户或进程给其他用户和进程发生异步信息的一种方式。对于信号我们可以根据实际生活,对他有以下几点认识:1.在没有产生信号时我们就知道产生信号要怎么处理(如古代时边境产生烽火,就要集结军队)。2.当信号产生时如果进程在忙着其他工作,信号需要保存,合适时候再处理。3.信号的产生是随机的,我们无法预测,所以信号是异步发生的。我们根据生活中的信号,可以对进程中的信号做出以上认识,下面我们来深入学习Linux信号.

2.信号的产生

1.kill命令产生信号

输入kill -l,我们可以查看操作系统中的各种信号,1-31为非实时信号,32-64为实时信号。

kill 命令后接-数字对应的信号再接进程pid,就可以对指定的进程发生指定的信号。如kill -9 2276702就可以对2276702号进程发送9号信号。

2. 通过终端按键产生信号

        如我们在进程运行的过程中,按下ctrl + c:向当前进程发送2号信号。 ctrl + :向当前进程发送3号信号。 ctrl + z:向当前进程发送20号信号等,我们可以通过键盘来发信号。

3.硬件异常产生信号

        硬件异常被硬件以某种方式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如当前进程执行了除 以0的指令,CPU的运算单元会产生异常,内核将这个异常解释 为SIGFPE信号发送给进程。再比如当前进程访问了非 法内存地址,,MMU会产生异常,内核将这个异常解释为SIGSEGV信号发送给进程。

4.由软件条件产生信号

如管道在写端打开,读端关闭时会产生13号信号给进程,由软件条件也会产生信号。

2.信号的保存及阻塞

1.相关概念:

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

2.实现原理

 task_struct 的某个指针指向三张位图block(阻塞),pending(未绝),handler(处理),其中位图中下标数字+1表示几号信号。在block位图中元素为0代表不阻塞信号,为1则要阻塞,如上图block就表示要阻塞2号信号和3号信号。pending也类似,0表示没有信号需处理,1表示有信号需处理,如上图就表示1号信号需处理。hander位图则存入对应的处理方法指针,表示对应信号的处理动作。

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

3.对pending,block位图操作

1.信号集操作函数
#include <signal.h>
int sigemptyset(sigset_t *set);//对信号集全置0
int sigfillset(sigset_t *set);//对信号集全置1
int sigaddset (sigset_t *set, int signo);//将信号集指定的signal信号位置1
int sigdelset(sigset_t *set, int signo);//将信号集指定的signal信号位置0
int sigismember(const sigset_t *set, int signo);//判断信号是否在信号集中为1
 

     这四个函数都是成功返回0,出错返回-1。

2.sigprocmask函数

调用函数sigprocmask可以读取或更改进程的信号屏蔽字(阻塞信号集)。

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset); 
返回值:若成功则为0,若出错则为-1 

oset为输出型参数,读取进程的当前信号屏蔽字通过oset参数传出进行保存。set是输入型参数,按照set更改进程的信号屏蔽字。参数how指示如何更改。下图是how的可选值及作用:

3.sigpending函数

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

#include <signal.h>
int sigpending(sigset_t *set);
 
4.代码讲解 

这里我们模拟一种情况来使用上面的函数,加深理解。我们先屏蔽2号信号,打印pending位图,然后输入2号信号,20秒后再解除2号的屏蔽再输入2号信号,代码如下

#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cassert>
#include <sys/wait.h>

void PrintSig(sigset_t &pending)
{
    std::cout << "Pending bitmap: ";
    for (int signo = 31; signo > 0; signo--)
    {
        if (sigismember(&pending, signo))
        {
            std::cout << "1";
        }
        else
        {
            std::cout << "0";
        }
    }
    std::cout << std::endl;
}
int main()
{
  
    // 1. 屏蔽2号信号
    sigset_t block, oblock;
    sigemptyset(&block);//全置零
    sigemptyset(&oblock);//全置零
    sigaddset(&block, 2); //此时只是对block变量进行修改没有设置进当前进程的PCB block位图中

    int n = sigprocmask(SIG_SETMASK, &block, &oblock);//将block变量置进当前进程的PCB block位图中
   
    std::cout << "block 2 signal success" << std::endl;
    std::cout << "pid: " << getpid() << std::endl;
    int cnt = 0;
    while (true)
    {
        // 2. 获取进程的pending位图
        sigset_t pending;
        sigemptyset(&pending);
        n = sigpending(&pending);
       

        // 3. 打印pending位图中的收到的信号
        PrintSig(pending);
        cnt++;

        // 4.20秒后解除对2号信号的屏蔽
        if (cnt == 20)
        {
            std::cout << "解除对2号信号的屏蔽" << std::endl;
            n = sigprocmask(SIG_UNBLOCK, &block, &oblock); // 2号信号会被立即递达, 默认处理是终止进程
            assert(n == 0);
        }
        // 我还想看到pending 2号信号 1->0 : 递达二号信号!
        sleep(1);
    }

    return 0;
}

运行结果: 

当我们屏蔽2号信号再输入2号信号时, 进程不能处理2号信号,放入pending位图中等候,解除屏蔽时2号信号可以处理,进程处理2号信号退出。

4.捕捉信号

1.什么时候处理信号

进程地址空间中存在用户空间(用户进程使用的内存资源)和内核空间(操作系统使用的内存资源),用户进程默认处于用户态,此时进程无法以任何形式访问操作系统的资源。当进程因系统调用,中断,异常或重新分配到时间片陷入内核态。

2.处理信号动作自定义的信号流程

当处理信号动作自定义的信号时,由于信号处理函数在用户态,为了不影响内核必须返回用户态。处理完后再返回内核执行完流程。简略图如下:

3.信号捕捉函数sigaction 
#include <signal.h>
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact); 

 sigaction函数可以读取和修改与指定信号相关联的处理动作。调用成功则返回0,出错则返回- 1。signo 是指定信号的编号。若act指针非空,则根据act修改该信号的处理动作。若oact指针非 空,则通过oact传 出该信号原来的处理动作。act和oact指向sigaction结构体:

其中第一个成员变量是函数指针,用于执行自定义动作,第三个变量表示我们需要添加的屏蔽信号,第四个置为0,其他我们暂时不讲解。

将sa_handler赋值为常数SIG_IGN传给sigaction表示忽略信号,赋值为常数SIG_DFL表示执行系统默认动作。该函数返回 值为void,可以带一个int参数,通过参数可以得知当前信号的编号,这样就可以用同一个函数处理多种信号。显然,这也是一个回调函数,不是被main函数调用,而是被系统所调用。

需要注意的是当某个信号处理函数被调用时,系统自动将当前信号加入信号屏蔽字,等信号处理函数调用完毕后再移除,这样是为了防止信号嵌套式进行捕捉处理。

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

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

相关文章

C++:特殊类的设计(无线程)

目录 一、设计一个不能拷贝类 二、设计一个只能在堆上创建对象的类 方法一&#xff1a;析构函数私有化 方法二&#xff1a;构造函数私有化 三、设计一个只能在栈上创建对象的类 四、设计一个类不能被继承 五、设计一个只能创建一个对象的类&#xff08;单例模式&#xf…

加盖骑缝章软件、可以给PDF软件加盖自己的骑缝章

加盖骑缝章的软件多种多样&#xff0c;尤其是针对PDF文件&#xff0c;有多种软件可以实现给PDF文件加盖自己的骑缝章。以下是一些常用的软件及其特点&#xff1a; 1. Adobe Acrobat Pro DC 特点&#xff1a; 多功能PDF编辑&#xff1a;Adobe Acrobat Pro DC是一款功能强大的…

开发必备基础知识【Linux环境变量文件合集】

开发必备基础知识【Linux环境变量文件合集】 在Linux系统中&#xff0c;环境配置文件用于定制用户的Shell环境&#xff0c;包括定义环境变量、设置命令别名、定义启动脚本等。不同的Shell&#xff08;如bash、zsh&#xff09;有着各自对应的配置文件。 .bashrc&#xff1a;每新…

【推荐图书】深入浅出Spring Boot 3.x

推荐原因 这部SpringBoot3.x经典之作&#xff0c;时隔六年迎来重磅升级&#xff01; 适合java开发相关读者 购买链接 商品链接&#xff1a;https://item.jd.com/14600442.html 介绍 书名&#xff1a;深入浅出Spring Boot 3.x ISBN&#xff1a;978-7-115-63282-1/ 作者&…

C语言之Const关键字与指针

目录 1 前言2 变量与指针的储存方式3 const int *var;int *const var&#xff1b;const int *const var&#xff1b;理解与区分4 总结 1 前言 实际开发过程中经常遇到const关键字作用于指针的情况&#xff0c;例如&#xff1a;const int *var;int *const var&#xff1b;const…

红薯小眼睛接口分析与Python脚本实现

文章目录 1. 写在前面2. 接口分析3. 算法脚本实现 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Py…

比 PIP 快 100 倍的安装工具

uv 是一个由 Rust 开发的 pip 工具&#xff0c;比 pip 快 100 倍&#xff0c;难以置信&#xff0c;不过真的是快太多了。 安装 在 Mac 上直接通过 brew install uv 安装即可。 venv 创建运行环境&#xff0c;默认当前目录下 .venv uv venv 依赖安装 uv pip install -r re…

Java | Leetcode Java题解之第217题存在重复元素

题目&#xff1a; 题解&#xff1a; class Solution {public boolean containsDuplicate(int[] nums) {Set<Integer> set new HashSet<Integer>();for (int x : nums) {if (!set.add(x)) {return true;}}return false;} }

谷粒商城学习笔记-14-项目结构创建提交到码云

一&#xff0c;码云上创建工程仓库 1&#xff0c;,点击右上角加号&#xff0c;选择新建仓库 2&#xff0c;填充必要信息 ①仓库名称&#xff0c;可以理解为工程名称。 ②仓库介绍&#xff0c;添加关于仓库的说明。 ③仓库权限设置&#xff0c;如果是公司项目&#xff0c;一般…

InnoDB内部结构

在mysql数据库中&#xff0c;InnoDB存储引擎是最为常用和强大的存储引擎之一。了解InnoDB的内存结构对于优化数据库的性能&#xff0c;提高系统的稳定性和扩展性至关重要。本文将深入探讨InnoDB的内存结构。 1.Buffer Pool Buffer Pool: 缓冲池&#xff0c;其作用是用来缓存表…

为什么https比http更安全

读完本文&#xff0c;希望你能明白&#xff1a; HTTP通信存在什么问题HTTPS如何改进HTTP存在那些问题HTTPS工作原理是什么 一、什么是HTTPS HTTPS是在HTTP上建立SSL加密层&#xff0c;并对传输数据进行加密&#xff0c;是HTTP协议的安全版。现在它被广泛用于万维网上安全敏感…

奇舞周刊第532期:奇舞团生日快乐~

时光荏苒&#xff0c;岁月如歌&#xff0c;转眼间&#xff0c;奇舞团13岁啦&#x1f382;&#x1f382;&#x1f382;《奇舞周刊》也陪伴大家来到了第532期。&#x1f44f;&#x1f44f; 致敬每一位读者和创作者&#xff0c;是你们的热情、陪伴和鼓励&#xff0c;让我们不断前进…

SpringBoot | 大新闻项目源码打包

对于一个完成好的后端项目&#xff0c;如何进行打包发送给其他人&#xff0c;在电脑上进行查看 1.在pom.xml添加&#xff1a; <build><plugins> <!-- 打包插件--><plugin><groupId>org.springframework.boot</groupId><art…

【HTML入门】第二课 - head标签下的常见表情们

目录 1 本节概要 2 head下的常见标签 2.1 网页编码设置 2.2 网页的标题 2.3 样式标签 3 head标签的内容不会显示到网页上 4 查看网页源代码 1 本节概要 上一节&#xff0c;我们说了HTML网页最基本的框架标签&#xff0c;说到标签分为head头部和body身体部分。这一小节呢…

文言文编程语言|老外来了也得先学论语

最近看到一个有意思的开源项目 wenyan&#xff0c;主要功能就是使用文言文来编写代码。 按项目说明 “Wenyan” 是一种遵循中国古典文学的语法和语调的编程语言。 此外&#xff0c;文言的字符集仅包含繁体汉字和「」引号&#xff0c;确保古代中国人能够阅读。 该编程语言的文…

C++:类的成员属性,公有,私有,保护

在C中级别&#xff0c;类的成员属性分为三种访问控制&#xff1a;公有&#xff08;public&#xff09;、私有&#xff08;private&#xff09;和保护&#xff08;protected&#xff09;。它们用于控制类内部数据对类外部的可见性和访问权限。设置访问属性对于封装和信息隐藏至关…

Truffle学习笔记

Truffle学习笔记 安装truffle, 注意: 虽然目前truffle最新版是 5.0.0, 但是经过我实践之后, 返现和v4有很多不同(比如: web3.eth.accounts; 都获取不到账户), 还是那句话: “nodejs模块的版本问题会搞死人的 !” 目前4.1.15之前的版本都不能用了, 只能安装v4.1.15 npm instal…

Beats:使用 Filebeat 从 Python 应用程序中提取日志

本指南演示了如何从 Python 应用程序中提取日志并将其安全地传送到 Elasticsearch Service 部署中。你将设置 Filebeat 来监控具有标准 Elastic Common Schema (ECS) 格式字段的 JSON 结构日志文件&#xff0c;然后你将在 Kibana 中查看日志事件发生的实时可视化。虽然此示例使…

SCI二区TOP|麋鹿群优化算法: 一种新颖的受自然启发的元启发式算法

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年&#xff0c;SO Oladejo受到麋鹿群的繁殖过程启发&#xff0c;提出了麋鹿群优化算法&#xff08;Elk herd optimizer, EHO&#xff09;。 2.算法原理 2.1算法思想 EHO灵感来自麋鹿…

Win11右键默认显示更多选项的方法

问题描述 win11系统默认右键菜单显示选项太少&#xff0c;每次需要点一下“显示更多选项”才能得到想要内容。比方说我用notepad打开一个文档&#xff0c;在win11上要先点一下"显示更多选项“&#xff0c;再选择用notepad打开&#xff0c;操作非常反人类。 Win11右键默…