深入理解Linux内核--信号

news2024/10/7 12:22:01

信号的作用

        信号(signal)是很短的消息,可以被发送到一个进程或一组进程。发送给进程的唯一信息通常是一个数,以此来标识信号。在标准信号中,对参数、消息或者其他相随的信息没有给予关注。

        使用信号的两个主要目的是:1.让进程知道已经发生了一个特定的事件。2.强迫进程执行它自己代码中的信号处理程序。

         

        除了在这张表中描述的常规信号(regular signal)外,POSIX标准还引入了一类新的信号,叫做实时信号(real-time signal);在Linux中它们的编码范围为32~64。它们与常规信号有很大的不同,因为它们必须排队以便发送的多个信号能被接收到。另一方面,同种类型的常规信号并不排队:如果一个常规信号被连续发送多次,那么,只有其中的一个发送到接收进程。尽管Linux内核并不使用实时信号,它还是通过几个特定的系统调用完全实现了POSIX标准。

        许多系统调用允许程序员发送信号,并决定他们的进程如何响应所接收的信号。表11-2简洁地描述了这些系统调用,更详细的内容将在后面“与信号处理相关的系统调用”一节中描述。

        信号的一个重要特点是它们可以随时被发送给状态经常不可预知的进程。发送给非运行进程的信号必须由内核保存,直到进程恢复执行。阻塞一个信号(后面描述)要求信号的传递拖延,直到随后解除阻塞,这使得信号产生一段时间之后才能对其传递这一问题变得更加严重。因此,内核区分信号传递的两个不同阶段:

信号产生

        内核更新目标进程的数据结构以表示一个新信号已被发送。

信号传递
         内核强迫目标进程通过以下方式对信号做出反应:或改变目标进程的执行状态,或
开始执行一个特定的信号处理程序,或两者都是。

         每个所产生的信号至多被传递一次。信号是可消费资源:一旦它们已传递出去,进程描述符中有关这个信号的所有信息都被取消。已经产生但还没有传递的信号称为挂起信号(pending signal)。任何时候,一个进程仅存在给定类型的一个挂起信号,同一进程同种类型的其他信号不被排队,只被简单地丢弃。

        但是,实时信号是不同的:同种类型的挂起信号可以有好几个。一般来说,信号可以保留不可预知的挂起时间。必须考虑下列因素:

1. 信号通常只被当前正运行的进程传递(即由current进程传递)。

2.给定类型的信号可以由进程选择性地阻塞(blocked)(参见“修改阻塞信号的集合”

一节)。这种情况下,在取消阻塞前进程将不接收这个信号。
3.当进程执行一个信号处理程序的函数时,通常“屏蔽”相应的信号,即自动阻塞这
个信号直到处理程序结束。因此,所处理的信号的另一次出现不能中断信号处理程
序,所以,信号处理函数不必是可重入的。
        尽 管信 比较直 但内核
1.记住每个进程阻塞哪些信号。

2.当核态对任进程个信

几乎在每个定时中断时都发生(大约每毫秒发生一次)。
3.确 是否 忽略信 发生 下列 件都
3.1. 目标进程没有被另一个 进程跟踪(进程描述符中pt race字段的PT_PTRACED
标志等于0)。
3.2.信号没有被目标进程阻塞。
3.3.信号 进程忽略 ( 为进 信号 进程
改变信号的缺省操作且这个缺省操作就是“忽略”)。

4.进程到一个信

号处 以后 下文
        
此外 Li nu x B S D S y s t em V 且, 与相
当麻烦的POSIX标准相兼容。

传递信号之前所执行的操作

        进程以三种方式对一个信号做出应答:

1. 显式地忽略信号。
2 . 行与 ( 1 1 - 1 )。由 核预定义 决于
的类型,可以是下列类型之一:
T e rm i n a t e
        进程被终止(杀死)。
D u m p
         进程 (杀 ) , 建包 程执行上 转储
件;这个文件可以用于调试。
l g n o re
        信号被忽略。
S t o p
         进程被停止,即把进 程置为TASK_STOPPED状态(参见第 三章的“进程状态”
)
C o n t i nu e
        如果进程被停止(TASK _STOPPED) ,就把它置为 TASK_RUNNING状态。
3. 通过调用相应的信号处理函数捕获信号。
 

        如果一个进程正在被跟踪时接收到一个信号,内核就停止这个进程,并向跟踪进程发送一个SIGCHLD可以使用SIGCOUNT号重踪进程的执行。

         注意,对一个信号的阻塞和忽略是不同的:只要信号被 阻塞,它就不被传递;只有在
信号解除阻塞后才传递它。而一个被忽略的信号总是被传递,只是没有进一步的操作。
        SIGKILL和SIGSTOP信号不可以被显式地忽略、捕获或 阻塞,因此,通常必须执行它
们的缺 S I G KILL S I GSTO P 允许具有适 权的 分别 止并停止任何进程(注2),不管程序执行时采取怎样的防御措施。

        如果信号的传递会引起内核杀死一个进程,那么这个信号对该进程就是致命的。SIGKILL总是致命而且作为Terminate信号及不程捕获的信号程也是致命进程所捕获信号对应的信号处理函数终止了这个进程,那么这个信号就不是致命的,因为进程自己选择了终止,而不是被内核杀死。

POSIX信号和多线程应用

        POSIX 1003.1标准对多线程应用的信号处理有一些严格的要求:

1.信号线程应线间共享过,线有自

的挂起信号掩码和阻塞信号掩码。
2.POSIX库函数kill()和sigqueue()(见稍后“与信号处理相关的系统调用”一
) 须向 所有 多线 某个 特殊 的线 程发 信号 所有由 内核 产生的
信号同样如此(如:SIGCHLD、SIGINT或SIGQUIT)。
3.每个发送给多线程应用的信 号仅传送给一个线程,这个 线程是由内核在从不会阻塞
该信号的线程中随意选择出来的。
4.如果向多线程应用发送了一 个致命的信号,那么内核将 杀死该应用的所有线程,而
不仅仅是杀死接收信号的那个线程。

        有两个例外:不可能给进程0(swapper)发送信号,而发送给进程1(init)的信号在捕

获到它们之前也总被丢弃。因此,进程0永不死亡,而进程1只有当init程序终止时才死
        
        为了遵循POSIX标准,Linux内核2.6把多线程应用实现为一组属于同一个线程组的轻
量级进程(参见第三章“进程、轻量级进程和线程”一节)。
        
        在本章中,术语“线程组”指任意一种线程 组,包括仅由 单一(普通)进程构成的线程
组。例如,当我们规定kill()能够向线程组发送信号时,我们的意思是这个系统调用
也能够向普通进程发送信号。我们将使用术语“进程”表示普通进程或轻量级进程,即
属于某个线程组的特定成员。
        
        此外,如果一个挂起信号被发送给了某个特定进程,那么这个信号是私有的;如果被发
送给了整个 线程组 ,它 就是共享的。

与信号相关的数据结构

        对系统中的每个进程来说,内核必须跟踪什么信号当前正在挂起或被屏蔽,以及每个

线程组是如何处理所有信号的。为了完成这些操作,内核使用几个从处理器描述符可
存取的数据结构。最重要的数据结构如图11-1所示。
        

         

        blocked字段存放进程当前所屏蔽的信号。它是一个sigset_t位数组,每种信号类型
对应 素: 
       
t y pe d e f s tr u c t {
        u n s i g n e d l o n g s i g [ 2 ] ;
} s i g s e t _ t ;

         因为每个无符号长整数由32位组成,所以在Linux中可以声明的信号最大数是64

(_NSIG宏表示这个值)。没有值为0的信号,因此,信号的编号对应于sigset_t类型

相应 1。1 3 1 的编号 对应 11 - 1 信号 ,而3 2 ~ 6 4
间的编号对应于实时信号。

信号描述符信号处程序描述符

         

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

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

相关文章

【Linux命令详解 | cat命令】Linux系统中用于显示或连接文件的命令

文章标题 简介一,参数列表二,使用介绍1. 显示文件内容2. 创建文件3. 连接文件4. 显示行号5. 压缩空行6. 显示特殊字符7. 显示行号和特殊字符8. 从标准输入读取9. 显示文件开头或结尾10. 备份文件11. 显示文件内容至多屏幕大小12. 转义正则表达式13. 显示…

线段树模板12

线段树 洛谷上有两道线段树模板(指模板1,模板2)都是区间维护的,也就是说,都离不开lasytag的维护,为了提高效率,故使用了lasytag,这里看一下题 【模板】线段树 1 题目描述 如题,已…

ChatGLM实战:基于LangChain构建自己的私有知识库

作者简介:赵辉,区块链技术专家,精通各种联盟链、公链的底层原理,拥有丰富的区块链应用开发经验。 在之前的 ChatGLM 微调训练的实验中,由于数据量较小,调试效果并不理想。同时,数据需要符合 Pro…

项目管理和产品管理之间的区别

产品管理和项目管理是两个在企业中至关重要的职能部门,它们各自承担着不同的职责和任务。虽然两者在某些方面存在重叠,但它们的核心目标和方法有很大的不同。本文将对产品管理和项目管理进行详细的比较和分析。 “项目管理和产品管理有什么区别&#xff…

一周 AIGC 丨苹果下架多款 AIGC 应用,阿里云开源通义千问 70 亿参数模型

多个 AIGC 应用在苹果应用商店下架,包含数据采集和使用不够规范等问题。阿里云开源通义千问 70 亿参数模型,包括通用模型 Qwen-7 B 和对话模型 Qwen-7 B-Chat。腾讯混元大模型开始应用内测,内部多个业务线接入测试。百度智能云“千帆大模型平…

textarea 标签如何创建多行文本输入框?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ textarea 的写法⭐ 代码含义⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅!这个专栏是为那些对Web开发感兴趣、…

看门狗文章

1. iwdg.c #include "stm32f4xx.h" #include "iwdg.h"//prer:预分频值 //rlr:自动重装载值 void IWDG_Init(unsigned char prer,unsigned int rlr)//IWDG初始化 {IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);…

Grafana V10 告警推送 邮件

最近项目建设完成,一个城域网项目,相关zabbix和grafana展示已经完,想了想,不想天天看平台去盯网络监控平台,索性对告警进行分类调整,增加告警的推送,和相关部门的提醒,其他部门看不懂…

linux网络编程--线程池UDP

目录 学习目标 1线程池 2.UDP通信 3本地socket通信 学习目标 了解线程池模型的设计思想能看懂线程池实现源码掌握tcp和udp的优缺点和使用场景说出udp服务器通信流程说出udp客户端通信流程独立实现udp服务器代码独立实现udp客户端代码熟练掌握本地套接字进行本地进程通信 1…

【网络】自定义协议 | 序列化和反序列化 | Jsoncpp

本文首发于 慕雪的寒舍 以tcpServer的计算器服务为例,实现用jsoncpp来进行序列化和反序列化 阅读本文之前,请先阅读 自定义协议 | 序列化和反序列化 | 以tcpServer为例 1.安装jsoncpp 我所用的系统是centos7.6,先用下面的命令查找相关的包 …

AST还原实战| 实战还原一个22M的混淆js大文件

关注它,不迷路。 本文章中所有内容仅供学习交流,不可用于任何商业用途和非法用途,否则后果自负,如有侵权,请联系作者立即删除! 1. 需求分析 之前有星友发了这个大文件在群里: https://t.zsxq.com/10…

CountDownLatch 使用详情

CountDownLatch 是 Java.util.concurrent 包下的一个类,它可以用来实现一个或多个线程等待其他线程完成后再继续执行的场景。 CountDownLatch 类中有一个计数器,每次调用 countDown() 方法计数器的值减1,当计数器的值变为0时,调用…

面向大模型的存储加速方案设计和实践

这是 AI 大底座系列云智公开课的第三期内容。前两期我的两位同事已经向大家介绍了高性能网络和 GPU 容器虚拟化的相关内容。今天我们把目光聚焦在存储方向,一起来看看面向大模型的存储加速方案的设计和实践。 今天将从以下三个方面来展开这次分享: 介绍…

APP外包开发的Flutter框架

Flutter 是一种流行的开源UI框架,由谷歌开发,用于构建跨平台的移动应用程序。它使用一套统一的代码库,可以在多个平台上(如Android、iOS、Web、桌面等)保持一致的外观和行为。今天和大家分享一些基于 Flutter 开发的常…

CI/CD持续集成持续发布(jenkins)

1.背景 在实际开发中,我们经常要一边开发一边测试,当然这里说的测试并不是程序员对自己代码的单元测试,而是同组程序员将代码提交后,由测试人员测试; 或者前后端分离后,经常会修改接口,然后重新…

【CSS】说说响应式布局

目录 一、是什么 二、怎么实现 1、媒体查询 2、百分比 3、vw/vh 4、小结 三、总结 一、是什么 响应式设计简而言之,就是一个网站能够兼容多个终端——而不是为每个终端做一个特定的版本。 响应式网站常见特点: 同时适配PC 平板 手机等…

代码随想录 - 数组

数组是存放在连续内存空间上的相同类型数据的集合。 注意: 数组下标都是从0开始的。数组内存空间的地址是连续的 数组的在内存空间的地址是连续的,所以在删除或者增添元素的时候,就难免要移动其他元素的地址。 例如删除下标为3的元素&#x…

SpringMVC的注解

文章目录 前言前期准备ResponseBody 返回JSONRequestMapping 映射控制器GetMapping、PostMapping 前言 提示:这里可以添加本文要记录的大概内容: SpringMVC框架只需要少量的配置即可快速实现Web应用程序开发,不需要大量的XML配置文件。 不…

【ES】笔记-简化对象写法箭头函数及声明特点

简化对象写法&箭头函数及声明特点 简化对象写法箭头函数及声明特点 简化对象写法 ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法.这样的书写更加简介 声明变量和和函数 let name南昌大学;let changefunction(){console.log(我可以改…

如何使用Kafka构建事件驱动的架构

事件驱动的架构(EDA)是一种软件设计模式,它关注事件的生成、检测和使用,以支持高效和可扩展的系统。在EDA中,事件是组件之间通信的主要手段,允许它们实时交互和响应更改。这种架构促进了松散耦合、可扩展性和响应性,使…