Linux信号

1. 什么是进程?

从内核的角度,进程是系统分配资源的单位。当一个程序(静态)被加载到内存,操作系统为程序分配一个PCB(进程控制块)。

PCB:Process Control Block。在Linux中PCB叫做task_struct的结构体,我们称之为“进程描述符”。它里面包含了进程执行的所有信息,所以操作系统CPU对task_struct进行管理,相当于对进程进程管理。每一个进程都有一个PCB。


2. 信号的内核表示与信号阻塞

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

3. 信号在内核中的表示

系统中的信号是发送给进程的,对于进程而言,信号是给进程的PCB(task_struct)发的,PCB使用位图结构(block位图、pending位图)结构记录收到的信号,这样进程执行时就知道自己收到什么信号了。

信号为什么要被保存在进程里?因为进程收到信号后,可能不会立即处理。这个信号从产生到递达之间的时间窗口内,进程需要记录该信号已经产生了,等到处理的时候才能知道哪些信号已经发生了。

  • 比特位的内容为1或0,表示是否收到某个信号
  • 比特位的位置(第几个),表示信号的编号c
  • 所谓的“发信号”,本质就是操作系统区修改tack_struct的信号位图的对应比特位,发送信号实际上就是写信号。

使用kill -l查看操作系统有哪些信号

kill -l

操作系统是进程的管理者,只有它才有资格去修改task_struct内部的属性,即操作系统需要提供相应的系统调用以实现信号的发送、阻塞等功能

task_struct中针对信号,包含了两张位图和一张函数指针表。分别是block位图pending位图handler处理函数指针表

  • block位图记录某个信号是否被阻塞,如果某个信号对应的比特为1表示该信号被阻塞,为0表示没有阻塞;对于被阻塞的信号,即使该信号产生了,进程也不会对该信号做任何处理。
  • pending位图记表示收到了哪些信号。如果收到某个信号,则会将对应的比特位置1;处理完某个信号后,会将对应的比特位置0。由于每个比特位只能表示信号的有无,若在信号产生到信号递达的时间窗口内,重复收到多个同样的信号,最终也只会递达一次。
  • handler函数指针数组用于记录对各个信号的处理方式。如果设置为SIG_DFL表示执行系统默认处理函数,设置为SIG_IGN表示忽略该信号;设置为用户空间的某个函数时,待信号递达时,则会从内核态切换回用户态以执行该部分代码

4. Linux常规信号一览表

1) SIGHUP: 当用户退出shell时,由该shell启动的所有进程将收到这个信号,默认动作为终止进程

2) SIGINT:当用户按下了<Ctrl+C>组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号。默认动

作为终止进程。

3) SIGQUIT:当用户按下<ctrl+\>组合键时产生该信号,用户终端向正在运行中的由该终端启动的程序发出些信

号。默认动作为终止进程。

4) SIGILL:CPU检测到某进程执行了非法指令。默认动作为终止进程并产生core文件

5) SIGTRAP:该信号由断点指令或其他 trap指令产生。默认动作为终止里程 并产生core文件。

6) SIGABRT: 调用abort函数时产生该信号。默认动作为终止进程并产生core文件。

7) SIGBUS:非法访问内存地址,包括内存对齐出错,默认动作为终止进程并产生core文件。

8) SIGFPE:在发生致命的运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为0等所有的算法错误。默认动作为终止进程并产生core文件。

9) SIGKILL:无条件终止进程。本信号不能被忽略,处理和阻塞。默认动作为终止进程。它向系统管理员提供了可以杀死任何进程的方法。

10) SIGUSE1:用户定义 的信号。即程序员可以在程序中定义并使用该信号。默认动作为终止进程。

11) SIGSEGV:指示进程进行了无效内存访问。默认动作为终止进程并产生core文件。

12) SIGUSR2:另外一个用户自定义信号,程序员可以在程序中定义并使用该信号。默认动作为终止进程。

13) SIGPIPE:Broken pipe向一个没有读端的管道写数据。默认动作为终止进程。

14) SIGALRM: 定时器超时,超时的时间 由系统调用alarm设置。默认动作为终止进程。

15) SIGTERM:程序结束信号,与SIGKILL不同的是,该信号可以被阻塞和终止。通常用来要示程序正常退出。执行shell命令Kill时,缺省产生这个信号。默认动作为终止进程。

16) SIGSTKFLT:Linux早期版本出现的信号,现仍保留向后兼容。默认动作为终止进程。

17) SIGCHLD:子进程状态发生变化时,父进程会收到这个信号。默认动作为忽略这个信号。

18) SIGCONT:如果进程已停止,则使其继续运行。默认动作为继续/忽略。

19) SIGSTOP:停止进程的执行。信号不能被忽略,处理和阻塞。默认动作为暂停进程。

20) SIGTSTP:停止终端交互进程的运行。按下<ctrl+z>组合键时发出这个信号。默认动作为暂停进程。

21) SIGTTIN:后台进程读终端控制台。默认动作为暂停进程。

22) SIGTTOU: 该信号类似于SIGTTIN,在后台进程要向终端输出数据时发生。默认动作为暂停进程。

23) SIGURG:套接字上有紧急数据时,向当前正在运行的进程发出些信号,报告有紧急数据到达。如网络带外数据到达,默认动作为忽略该信号。

24) SIGXCPU:进程执行时间超过了分配给该进程的CPU时间 ,系统产生该信号并发送给该进程。默认动作为终止进程。

25) SIGXFSZ:超过文件的最大长度设置。默认动作为终止进程。

26) SIGVTALRM:虚拟时钟超时时产生该信号。类似于SIGALRM,但是该信号只计算该进程占用CPU的使用时间。默认动作为终止进程。

27) SGIPROF:类似于SIGVTALRM,它不公包括该进程占用CPU时间还包括执行系统调用时间。默认动作为终止进程。

28) SIGWINCH:窗口变化大小时发出。默认动作为忽略该信号。

29) SIGIO:此信号向进程指示发出了一个异步IO事件。默认动作为忽略。

30) SIGPWR:关机。默认动作为终止进程。

31) SIGSYS:无效的系统调用。默认动作为终止进程并产生core文件。

34) SIGRTMIN ~ (64) SIGRTMAX:LINUX的实时信号,它们没有固定的含义(可以由用户自定义)。所有的实时信号的默认动作都为终止进程。

9) SIGKILL 和19) SIGSTOP信号,不允许忽略和捕捉,只能执行默认动作。甚至不能将其设置为阻塞。

5. 信号集操作函数

信号集操作函数
int sigemptyset(sigset_t *set)将传入的set位图的各个位清零
int sigfillset(sigset_t *set)将传入的set位图的各个位置设置为1
int sigaddset(sigset_t *set, int signum)将signum信号在set中对应的比特位置设置为1
int sigdelset(sigset_t *set, inst signum)将signum信号在set中对应的比特位置设置为0
sigismember(const sigset_t *set, int signum)查看signum对应的比特位在set中是否为1,为1则返回1,否则返回0

注意,在使用sigset_t类型的变量之前,一定要调用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。初始化sigset_t变量之后,可以调用sigaddset和sigdelset在该信号集中添加或删除某种信号。

上述接口只是对sigset_t这个位图结构做操作,并未对block和pending位图直接做操作,下面介绍关于这两个位图的系统调用函数:sigprocmask和sigpending

5.1 sigprocmask读取/修改进程的信号屏蔽字(阻塞信号集/blocking位图)

第一个参数:how

how可以取值SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK.

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

第二个参数:set

用户自己定义的sigset_t类型的set

第三个参数:oldset

oldset是传出参数,调用sigprocmask系统调用函数之后,会传出调用该函数之前的进程的mask位图。

5.2 获取当前进程的信号屏蔽字

#include <stdio.h>
#include <signal.h>int main(){sigset_t oldset;sigprocmask(SIG_BLOCK,NULL,&oldset);for (int i = 1; i < NSIG; i++){if(sigismember(&oldset,i))printf("1");elseprintf("0");}printf("\n");return 0;
}

 注意:NSIG的取值是最大的信号数+1

5.3 信号集操作函数练习

#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
void sys_err(const char *str){perror(str);exit(1);
}void print_set(sigset_t *set){int i;for (i = 1; i < 32; i++){if (sigismember(set,i))putchar('1');elseputchar('0');}printf("\n");
}int main(){sigset_t set, oldset, pedset;int ret = 0;sigemptyset(&set);sigaddset(&set,SIGINT);ret = sigprocmask(SIG_BLOCK,&set,&oldset);if (ret == -1)sys_err("sigprocmask error");while(1){ret = sigpending(&pedset);if (ret == -1)sys_err("sigpending error");print_set(&pedset);sleep(1);}}

6. signal实现信号捕捉

注册一个信号捕捉函数。

该函数由ANSI定义,由于历史原因在不同版本的Unix和不同版本的Linux中可能有不同的行为。因此应该尽量避免使用它,取而代之使用sigaction函数。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>void sig_catch(int signo){printf("catch you!!%d\n",signo);return;
}int main(){signal(SIGINT,sig_catch);while(1);return 0;}

7. sigaction实现信号捕捉

  注意sigaction的信号屏蔽字sa_mask,其作用域只存在于信号捕捉函数执行期间生效

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>void sig_catch(int signo){printf("catch you!!%d\n",signo);return;
}int main(){struct sigaction act, oldact;act.sa_handler = sig_catch;sigemptyset(&(act.sa_mask));act.sa_flags = 0;int ret = sigaction(SIGINT,&act,&oldact);while(1);return 0;}

8. 信号捕捉的特性

  • 进程正常运行时,默认PCB中有一个信号屏蔽字,假定为△,它决定了进程自动屏蔽哪些信号。当注册了某个信号捕捉函数,捕捉到该信号后,要调用该函数。而该函数有可能执行很长时间,在这期间所屏蔽的信号不由△来指定。而是用sa_mask来指定。调用完信号处理函数,再恢复为△。
  • XXX信号捕捉函数执行期间,XXX信号自动被屏蔽(sa_flags = 0)
  • 阻塞的常规信号不支持排队,产生多次只记录一次。

9. 内核实现信号捕捉间析

10. 借助信号捕捉回收子进程

SIGCHILD的产生条件:

  • 子进程终止时
  • 子进程接收到SIGSTOP信号停止时
  • 子进程处在停止位置,接收到SIGCONT后唤醒时

借助SIGCHILD信号回收子进程:

子进程结束运行,其父进程会收到SIGCHILD信号。该信号的默认处理动作是忽略。可以捕捉该信号,在捕捉函数中完成子进程状态的回收。

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

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

相关文章

07-案例-图书管理

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

js中typeOf无法区分数组对象

[TOC]&#xff08;js中typeOf无法区分数组对象) 前提&#xff1a;很多时候我们在JS中用typeOf来判断值类型&#xff0c;如&#xff1a;typeOf ‘abc’//string ,typeOf 123 //number; 但当判断对象为数组时返回的仍是’object’ 这时候我们可以使用Object.prototype.toString.c…

【时间之外】IT人求职和创业应知【36】-肖申克的救赎

目录 新闻一&#xff1a;信息技术应用创新产业大会在深圳开幕 新闻二&#xff1a;人工智能与大数据融合应用成为创业新热点 新闻三&#xff1a;云计算与边缘计算协同发展推动IT行业创新 认知和思考决定了你的赚钱能力。以下是今天可能引起你思考的热点新闻&#xff1a; 新闻…

STL之vecor的使用(超详解)

目录 1. C/C中的数组 1.1. C语言中的数组 1.2. C中的数组 2. vector的接口 2.1. vector的迭代器 2.2. vector的初始化与销毁 2.3. vector的容量操作 2.4. vector的访问操作 2.5. vector的修改操作 &#x1f493; 博客主页&#xff1a;C-SDN花园GGbond ⏩ 文章专栏…

Python异常处理day8

1、异常处理机制 1.1内置异常 常见的内置异常&#xff0c;修改元组&#xff0c;输出变量为被定义&#xff0c;强转错误&#xff0c;将字符串转成整型&#xff0c;索引超范围&#xff0c;除数不能为0&#xff0c;引用未被定义的模组&#xff0c;字符串与整型加减&#xff0c;各…

FFmpeg 4.3 音视频-多路H265监控录放C++开发十三.2:avpacket中包含多个 NALU如何解析头部分析

前提&#xff1a; 注意的是&#xff1a;我们这里是从avframe转换成avpacket 后&#xff0c;从avpacket中查看NALU。 在实际开发中&#xff0c;我们有可能是从摄像头中拿到 RGB 或者 PCM&#xff0c;然后将pcm打包成avframe&#xff0c;然后将avframe转换成avpacket&#xff0…

软件测试之缺陷编写

软件测试之缺陷编写 1. 缺陷报告示例2. 缺陷的跟踪流程3. 提交缺陷注意事项 1. 缺陷报告示例 2. 缺陷的跟踪流程 发现bug后怎么办? 要确认bug的可复现. 3. 提交缺陷注意事项

建筑工程内部知识库:提升项目管理效率的关键

在建筑工程领域&#xff0c;项目管理的效率直接关系到项目的成本、进度和质量。随着信息技术的快速发展&#xff0c;内部知识库已成为提升项目管理效率的关键工具。本文将探讨如何通过内部知识库优化建筑工程项目管理&#xff0c;并提供一些实用的策略和建议。 一、内部知识库…

Vue前端开发之组件事件

在一个组件中&#xff0c;不仅可以定义属性&#xff0c;还能定义事件&#xff0c;同时&#xff0c;在定义的事件中&#xff0c;还可以传递事件参数&#xff0c;校验参数&#xff0c;组件中定义的事件&#xff0c;可以被调用此组件的父级组件监听&#xff0c;当触发子级组件的事…

Springboot 整合 Java DL4J 打造金融风险评估系统

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

【Unity】ScriptableObject的应用:利用配方合成新物体

前一篇已经使用ScriptableObject(SO)类配置可放置物体&#xff0c;本篇探索更多的SO类应用场景。 需求分析 将若干指定物体放在工作台上&#xff0c;可以生成新的物体。 成果展示 Scene部分 准备工作台&#xff0c;放在工作台上的物体全部放在指定PlacedObjects空物体下。 …

实践1:创建 POST、GET、DELETE 请求

好的&#xff0c;以下是关于HTTP请求的详细内容&#xff1a; 一、HTTP请求 HTTP&#xff08;HyperText Transfer Protocol&#xff09;是用于在Web浏览器和服务器之间传输数据的协议。它是Web的基础&#xff0c;也是RESTful API通信的核心。HTTP请求由客户端&#xff08;如浏…

每日小题--买股票的最佳时机

目录 题目 分析 解题思路 完整代码 题目 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润…

企业一站式管理系统odoo的研究——PLM插件的搭建

大纲 1. 环境准备1.1 安装操作系统1.2 更新操作系统1.3 配置用户组和用户1.3.1 创建用户组 odoo1.3.2. 创建用户 odoo1.3.3. 设置用户 odoo 的密码1.3.4. 验证用户和组1.3.5. 将用户 odoo 添加到添加sudo组&#xff1a;1.3.6. 切到odoo用户 2. 安装 Odoo1. 安装依赖项目2.2. 安…

泰矽微重磅发布超高集成度车规触控芯片TCAE10

市场背景 智能按键和智能表面作为汽车智能化的重要部分&#xff0c;目前正处于快速发展阶段&#xff0c;电容式触摸按键凭借其操作便利性与小体积的优势&#xff0c;在汽车内饰表面的应用越来越广泛。对于空调控制面板、档位控制器、座椅扶手、门饰板、车顶控制器等多路开关的…

10月回顾 | Apache SeaTunnel社区动态与进展一览

各位热爱 Apache SeaTunnel 的小伙伴们&#xff0c;社区10月份月报来啦&#xff0c;请查收&#xff01; 这里将记录Apache SeaTunne社区每月动态和进展&#xff0c;欢迎关注。 月度Merge之星 感谢以下小伙伴上个月为 Apache SeaTunnel 所做的精彩贡献&#xff08;排名不分先…

__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ is not explicitly defined

VUE_PROD_HYDRATION_MISMATCH_DETAILS 未明确定义。您正在运行 Vue 的 esm-bundler 构建&#xff0c;它期望这些编译时功能标志通过捆绑器配置全局注入&#xff0c;以便在生产捆绑包中获得更好的tree-shaking优化。 Vue.js应用程序正在使用ESM&#xff08;ECMAScript模块&#…

浪潮信息“源”Embedding模型登顶MTEB榜单第一名

在自然语言处理&#xff08;NLP&#xff09;和机器学习领域&#xff0c;Embedding模型是将文本数据转换为高维向量表示的核心技术&#xff0c;直接影响NLP任务&#xff08;如文本分类、情感分析等&#xff09;的效果&#xff0c;对于提升模型性能和深入理解文本语义具有至关重要…

一文6个步骤带你实现接口测试入门

软件测试资料领取&#xff1a;[内部资源] 想拿年薪40W的软件测试人员&#xff0c;这份资料必须领取~ 软件测试面试刷题工具&#xff1a;软件测试面试刷题【800道面试题答案免费刷】 一、接口测试概述 1 什么是接口测试&#xff1a; 接口测试是测试系统组件间交互的一种测试…

成人失禁护理领导品牌可靠亮相广州SIC老博会 助力推动养老产业高质量发展

2024年11月15日至17日&#xff0c;第十届中国国际老龄产业博览会&#xff08;SIC老博会&#xff09;在广州保利世贸博览馆开幕。可靠股份&#xff08;股票代码&#xff1a;301009&#xff09;携成人失禁护理系列等经典及战略产品受邀亮相本次展会&#xff0c;全方位展示企业在产…