Linux信号处理机制基础

news/2024/9/17 21:33:52/ 标签: 信号处理, linux, vim, 开发语言, c语言, vscode

什么是信号

  • 信号在最早的UNIX系统中即被引入,已有30多年的历史,但只有很小的变化。
  • 信号是提供异步事件处理机制的软件中断
  • 进程之间可以相互发送信号,这使信号成为一种进程间通信(Inter-ProcessCommunication,lPC)的基本手段

信号的名称与编号

  • 信号是很短的消息,本质就是一个整数,用以区分代表不同事件的不同信号。为了便于记忆,在signum.h头文件中用一组名字前缀为SIG的宏来标识信号,即为信号的名字。
  • 通过kill -l命令可以查看信号
  • 一共有62个信号,其中前31个信号为不可靠的非实时信号后31个为可靠的实时信号

 常用信号

信号处理 

  • 忽略:什么也不做,SIGKILL(9)和SIGSTOP(19)不能被忽略
  • 默认:在没有人为设置的情况,系统缺省的处理行为。
  • 捕获:接收到信号的进程会暂停执行,转而执行一段事先编写好的处理代码,执行完毕后再从暂停执行的地方继续运行,

信号处理函数 

signal函数

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);

功能:设置调用进程针对特定信号的处理方式

参数:signum         信号编号
        handler 信号的处理方式,可以如下取值
                SIG_IGN        -忽略
                SIG_DFL       - 默认
                信号处理函数指针        -捕获 
返回值:成功返回原信号处理方式,如果之前未处理过则返回NULL,失败返回SIG_ERR

 代码演示

//信号处理
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
//信号处理函数
void sigfun(int signum){printf("%d进程:捕获到%d号信号\n",getpid(),signum);}
int main(){// 对2号信号进行忽略处理//接下来程序就有了忽略2号信号的能力if(signal(SIGINT,SIG_IGN) == SIG_ERR){perror("signal");return -1;}//对2号信号进行捕捉处理if(signal(SIGINT,sigfun) == SIG_ERR){perror("signal");return -1;}// if(signal(SIGINT,SIG_DFL) == SIG_ERR){//     perror("signal");//     return -1;// }for(;;);return 0;
}

 信号处理流程

        当有信号到来时,内核会保存当前进程的栈帧,然后再执行信号处理函数。当信号处理函数结束后,内核会恢复之前保存的进程的栈帧,使之继续执行

太平间信号

        无论一个进程是正常终止还是异常终止,都会通过系统内核向其父进程发送SIGCHLD(17)信号。父进程完全可以在针对SIGCHLD(17)信号的信号处理函数中,异步地回收子进程的僵尸,简洁而又高效

        信号处理函数执行期间,如果有多个相同的信号到来,则只保留一个,其余统统丢弃。如果我们在一次信号处理函数执行期间只进行一次收尸,就会导致漏网的僵尸。那我们又该如何对这些僵尸进程进行回收,我们可以在一次信号处理函数期间尽可能多的回收僵尸进程。此外为防止长时间等待回收子进程影响父进程的执行,我们可以采用非阻塞方式回收僵尸进程。

代码演示 

//太平间信号
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<sys/wait.h>
#include<errno.h>//信号捕获处理函数
void sigchild(int signum){printf("%d进程:捕获到%d号信号\n",getpid(),signum);sleep(2);//假装信号处理函数很耗时for(;;){pid_t pid = waitpid(-1,NULL,WNOHANG);if(pid == -1){if(errno == ECHILD){printf("%d进程:没有子进程了\n",getpid());break;}else{perror("waitpid");return ;}}else if(pid == 0){printf("子进程正在运行,回收不了\n");   break;}else{printf("%d进程:回收了%d进程的僵尸\n",getpid(),pid);}}
}/*for(;;){pid_t pid = wait(NULL);if(pid == -1){if(errno == ECHILD){printf("%d进程:没有子进程了\n",getpid());break;}else{perror("wait");return ;}}printf("%d进程:回收了%d进程的僵尸\n",getpid(),pid);}
}*/
int main(){if(signal(SIGCHLD,sigchild) == SIG_ERR){perror("signal");return -1;}//创建多个子进程for(int i = 0; i < 5;i++){pid_t pid = fork();if(pid == -1){perror("fork");return -1;}if(pid == 0){printf("%d进程:我是子进程\n",getpid());//sleep(1 + i);sleep(1);return 0;}}//创建老六pid_t oldsix = fork();if(oldsix == -1){perror("fork");return -1;}if(oldsix == 0){printf("%d进程:我是老六\n",getpid());sleep(15);return 0;}//父进程代码for(;;);return 0;
}

信号的继承与恢复

  • fork函数创建的子进程会继承父进程的信号处理方式
    • 父进程中对某个信号进行捕获,则子进程中对该信号依然捕获
    • 父进程中对某个信号进行忽略,则子进程中对该信号依然忽略

代码演示 

//验证子进程是否继承父进程的信号处理方式
#include <stdio.h>
#include<unistd.h>
#include<signal.h>
#include<sys/wait.h>void sigfun(int signum){printf("%d进程:捕获到%d号信号\n",getpid(),signum);
}
int main(){//忽略2号信号if(signal(SIGINT,SIG_IGN) == SIG_ERR){perror("signal");return -1;}//捕获3号信号if(signal(SIGQUIT,sigfun) == SIG_ERR){perror("signal");return -1;}//创建子进程pid_t pid = fork();if(pid == -1){perror("fork");return -1;}//子进程暂时不结束if(pid == 0){printf("%d进程:我是子进程\n",getpid());while(1){}return 0;}//父进程printf("%d进程:我是父进程\n",getpid());sleep(1);return 0;
}

 由于父子进程共用终端设备我们需要在vi上进行,开启两个窗口,向子进程发送2号和3号信号。

窗口1 
day06$./fork
18338进程:我是父进程
18339进程:我是子进程
day06$kill -2 18317
day06$
day06$kill -3 18317
day06$kill -3 18317
day06$kill -3 18317
窗口2
day06$./fork
18316进程:我是父进程
18317进程:我是子进程
day06$18317进程:捕获到3号信号
18317进程:捕获到3号信号
18317进程:捕获到3号信号
  • exec家族函数创建的新进程对信号的处理方式和原进程稍有不同
    • 原进程中被忽略的信号,在新进程中依然被忽略
    • 原进程中被捕获的信号,在新进程中被默认处理

 代码演示

execl.c

//新进程是否继承旧进程的信号处理方式
#include <stdio.h>
#include<unistd.h>
#include<signal.h>
//信号处理函数
void sigfun(int signum){printf("%d进程:捕获到%d号信号\n",getpid(),signum);return 0;
}
int main(){//忽略SIGINT信号if(signal(SIGINT,SIG_IGN) == SIG_ERR){perror("signal");return -1;}//捕获SIGQUIT信号if(signal(SIGQUIT,sigfun) == SIG_ERR){perror("signal");return -1;}//变身if(execl("./new","new",NULL) == -1){perror("execl");return -1;}return 0;
}

new.c

//变身目标
#include<stdio.h>
int main(){while(1){}return 0;
}
day06$./execl
^C^C^C^C^C^C^C^C^C^\退出 (核心已转储)
day06$


http://www.ppmy.cn/news/1517013.html

相关文章

论文翻译:Multi-step Jailbreaking Privacy Attacks on ChatGPT

Multi-step Jailbreaking Privacy Attacks on ChatGPT https://arxiv.org/pdf/2304.05197 多步骤越狱隐私攻击对ChatGPT的影响 文章目录 多步骤越狱隐私攻击对ChatGPT的影响摘要1 引言2 相关工作3 对ChatGPT的数据提取攻击3.1 数据收集3.2 攻击制定3.3 从ChatGPT中提取私人数据…

Java——动态代理(2/2)-动态代理的应用场景和好处(原始模块、使用代理、测试执行)

目录 使用代理优化用户管理类 原始模块 使用代理 测试执行 解决实际问题、掌握使用代理的好处 使用代理优化用户管理类 场景 某系统有一个用户管理类&#xff0c;包含用户登录&#xff0c;删除用户&#xff0c;查询用户等功能&#xff0c;系统要求统计每个功能的执行耗…

MySQL和Hadoop

一、介绍 MySQL 针对结构化数据的存储、管理、查询 mysql和hadoop下的部分都是数据库&#xff0c;mysql用sql,hadoop用的是hiveql。&#xff08;大数据vs小数据&#xff09;&#xff08;结构化vs分布式&#xff09; Hadoop 定义&#xff1a;Hadoop 是一个开源的框架&#x…

小程序常用界面交互api

1. wx.showToast 显示消息提示框 显示一个消息提示框&#xff0c;一般用于操作成功后的提示 wx.showToast({title: 操作成功,icon: success,duration: 2000 });2. wx.showModal 显示模态弹窗 显示一个模态弹窗&#xff0c;可以用于提醒用户重要信息或让用户进行选择 wx.sho…

c++自定义迭代器,如跳表,怎么实现

在C中&#xff0c;跳表是一种高效的数据结构&#xff0c;用于存储有序数据并支持快速查找、插入和删除操作。为了在C类中实现跳表迭代器&#xff0c;你需要定义一个迭代器类&#xff0c;并在跳表类中提供相应的接口。以下是一个简单的实现示例&#xff1a; #include <iostr…

C++STL之list的使用详解

一、简介 1、底层&#xff1a;list为双向链表&#xff0c;即struct中包含一个数据和两个指针&#xff0c;分别指向前一个节点和后一个节点&#xff0c;在堆上分配空间&#xff0c;每插入一个元数都会分配空间&#xff0c;每删除一个元素都会释放空间 2、性能 ① 访问&#x…

【JPCS独立出版,EI稳定检索】2024年工业机器人与先进制造技术国际学术会议(IRAMT 2024,9月27-29)

2024年工业机器人与先进制造技术国际学术会议&#xff08;IRAMT 2024&#xff09;将于2024年9月27-29日在中国成都举办。 此次会议将围绕工业机器人、机电技术、机械及制造等领域的最新研究成果展开讨论&#xff0c;并广泛邀请了国内外领域内的著名专家与学者。会议旨在搭建一个…

序列化组件对比

1、msgpack介绍 1.MsgPack产生的数据更小&#xff0c;从而在数据传输过程中网络压力更小 2.MsgPack兼容性差&#xff0c;必须按照顺序保存字段 3.MsgPack是二进制序列化格式&#xff0c;兼容跨语言 官网地址&#xff1a; https://msgpack.org/ 官方介绍&#xff1a;Its lik…

【Python机器学习】NLP概述——深度处理

自然语言处理流水线的各个阶段可以看作是层&#xff0c;就像是前馈神经网络中的层一样。深度学习就是通过在传统的两层机器学习模型架构&#xff08;特征提取建模&#xff09;中添加额外的处理层来创建更复杂的模型和行为。 上图中&#xff0c;前四层对应于聊天机器人流水线中的…

<数据集>遥感船舶识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;15047张 标注数量(xml文件个数)&#xff1a;15047 标注数量(txt文件个数)&#xff1a;15047 标注类别数&#xff1a;25 标注类别名称&#xff1a;[Aircraft Carrier, Auxiliary Ships, Other Ship, Other Warship,…

【51单片机实物】基于51单片机设计的简易直流电机调测速系统(可用在普中开发板)——程序源码设计文档演示视频等(文末工程资料下载)

基于51单片机设计的简易直流电机调测速系统 演示视频 基于51单片机设计的简易直流电机调测速系统(可用在普中开发板) 功能任务描述:将设置的转速与当前测量的转速比较,得出差值用于控制DAC0832的输出电压,从而控制直流电机的转速,使转速逐渐达到设置转速。在LED上显示设…

【代码随想录训练营第42期 Day39打卡 - 打家劫舍问题 - LeetCode 198.打家劫舍 213.打家劫舍II 337.打家劫舍III

目录 一、做题心得 二、题目与题解 题目一&#xff1a;198.打家劫舍 题目链接 题解&#xff1a;动态规划 题目二&#xff1a;213.打家劫舍II 题目链接 题解&#xff1a;动态规划 题目三&#xff1a;337.打家劫舍III 题目链接 题解&#xff1a;动态规划 三、小结 一、…

通过React实现萤石摄像头rtsp地址格式的视频流的web展示

首先&#xff0c;我们需要拿到rtsp格式的流地址&#xff08;rtsp://admin:[password][ip]&#xff09;&#xff0c;其中 password:设备底下的6位数验证码 ip:设备的ipv4地址 这里拿到ip的方式可以直连网线和绑定wifi两种方式 然后下载PC端的萤石工作室&#xff08;下载中心…

五、Centos7-安装Jenkins

目录 一、基础环境准备 1.安装JDK 2.安装Tomcat 二、安装Jenkins 1.配置Jenkins插件镜像源 2.问题&#xff1a;进入manager jenkins页面报错 3.配置Git 4.配置jdk 三、重新安装Jenkins 四、另一种Centos安装jenkins的方式--最终可用版 克隆了一个base的虚拟机&#x…

UnrealEngine学习(01):安装虚幻引擎

1. 下载安装 Epic Games 目前下载UE引擎需要先下载Epic Games&#xff0c;官网为我们提供了下载路径&#xff1a; https://www.unrealengine.com/zh-CN/downloadhttps://www.unrealengine.com/zh-CN/download 我们点击图中步骤一即可进行下载。 注释&#xff1a;Unreal Engi…

未初始化的变量

学习C语言局部变量&#xff0c;经常听到这个说法。为什么局部变量默认是未初始化的&#xff1f;解释它需要理解程序结构和栈操作。 栈内存 C/C函数的局部变量保存在栈&#xff0c;栈可以认为是操作系统为了“加速”程序运行给线程配置了一块临时使用的内存区域&#xff0c;如果…

Spring Boot 框架中配置文件 application.properties 当中的所有配置大全

Spring Boot 框架中配置文件 application.properties 当中的所有配置大全 &#xff03;SPRING CONFIG&#xff08;ConfigFileApplicationListener&#xff09; spring.config.name &#xff03;配置文件名&#xff08;默认 为 application &#xff09; spring.config.lo…

一个干净的python项目(没连数据库啥的)

希望你们写代码有用&#xff08;直接可以拿来用&#xff0c;我只要您的一个关注和赞赞&#xff09; #用户数据 user1{"用户名":"aaa","密码":"123","姓名":"热孜娅","类型":"客户"} user2{&q…

Python 爬虫框架

Python 中有许多强大且主流的爬虫框架&#xff0c;这些框架提供了更高级的功能&#xff0c;使得开发和维护爬虫变得更加容易。以下是一些常用的爬虫框架&#xff1a; 1. Scrapy - 简介: Scrapy 是 Python 最流行的爬虫框架之一&#xff0c;设计用于快速、高效地从网站中提取…

【Rust光年纪】文本分析利器:探索Rust语言的多功能文本处理库

从情感分析到关键词提取&#xff1a;Rust语言文本分析库详解 前言 随着自然语言处理技术的不断发展&#xff0c;对各种文本数据进行分析和处理的需求也在不断增加。本文将介绍一些用于Rust语言的文本分析和处理库&#xff0c;包括情感分析、自然语言处理、中文转换、语言检查…