0

0

linux异步信号handle浅析

WBOY

WBOY

发布时间:2024-02-13 22:03:13

|

500人浏览过

|

来源于良许Linux教程网

转载

linux系统是一种支持多任务并发执行的操作系统,它可以同时运行多个进程,从而提高系统的利用率和效率。但是,如果这些进程之间需要进行数据交换和协作,就需要使用一些进程间通信(ipc)的方式,例如消息队列、共享内存、信号量等。其中,信号是一种比较简单而灵活的ipc方式,它可以让一个进程向另一个进程发送一个简短的消息,通知它发生了某种事件或异常。linux系统中的信号有两种类型,分别是同步信号和异步信号。本文将浅析linux异步信号handle的方法,包括异步信号的含义、产生、发送、接收、处理和忽略等方面。

linux异步信号handle浅析

在初学linux编程的时候,一直觉得异步信号handle是个很神奇的东西,用户程序可以使用singal之类的系统调用为某某信号注册一个信号处理函数(handle函数)。
程序的二进制代码在内存中都有着确定的执行流程,为什么收到异步信号以后,程序会被“中断”,然后跳转到这个handle函数里面去运行呢?内核怎么有能力让程序做这样的跳转呢,总不可能临时修改程序的可执行代码吧?

后来学习了一些内核知识,才知道原来进程收到信号以后,并不是立即就被“中断”的,而是先在进程的控制结构(task_struct)中记录下收到了某某信号,然后等到进程即将从内核态返回用户态的时候,流程才被“中断”,handle函数才被调用。
用户进程什么时候会从内核态返回用户态呢?一般主要是三种情况:系统调用(用户进程主动进入内核)、中断(用户进程被动进入内核)、被调度执行(用户进程从等待执行变为正在执行)。
进程从收到信号到它从内核态返回用户态的过程,是需要一定时间的。但是这个时间一般会很短,至少时钟中断会以较大的频率(比如1毫秒一次)将用户进程带入内核(当然,只针对正在执行的进程)。

在进程即将从内核态返回用户态时,如果有信号需要处理,对应的handle函数将被调用(当然,可能没有注册handle,这时内核对信号进行默认的处理)。注意,现在进程还在内核态,内核是怎么调用用户态的handle函数的呢?
直接调用可以吗?当然不行。内核代码运行在高CPU特权级别下,如果直接调用handle函数,则handle函数也将在相同的CPU特权下被执行。那么用户将可以在handle函数里面为所欲为。
所以,调用handle必须先返回用户态。但是返回用户态后,程序流程又不受内核控制了,难不成内核还真的把用户进程的可执行代码临时改掉?

内核实际的做法还是比较巧妙。用户进程进入内核以后,都会在其对应的内核栈上留下返回地址,以便流程返回。内核调用handle函数的办法就是临时改掉栈上的返回地址,然后按原有的返回用户态的流程去返回。结果这一返回,就到了handle函数去了。(当然,需要修改的并不止是返回地址,而是一整个调用栈。)
虽然现在临时把返回地址改了,但是用户进程最终还是要返回到原先那个返回地址去的。那么,原先的返回地址及其调用栈应该保存在哪里呢?进程的内核栈空间有限,并且还需要应付handle函数中可能发生的系统调用,所以内核把这些信息放在内核栈上是不现实的,只能压到了用户栈上去。

当handle函数执行完毕,执行流程要返回到内核去。同样,由于CPU特权级别不同,从handle函数返回内核时不能单纯地利用RET指令去返回的。需要执行一次系统调用。

在handle执行完后,为什么要回到内核,再从内核返回到原始返回地址呢?如果直接返回到原始的返回地址那自然是很便捷。并且要这么做也不难,原始返回地址及其调用栈已经被压到了用户栈上,内核只需要在handle函数的调用栈上稍做手脚就行了。
1、返回到原始返回地址并不是回到那个地址就行了,需要把整个现场都恢复(主要是寄存器什么的)。当然,内核也可以在用户栈上面压一些代码,来完成这些事情;
2、现在可能不止一个信号要处理,最好让用户进程返回内核,继续处理其他信号;

为了返回内核,首先,内核在返回到handle函数之前,先将某个返回地址压到用户栈上,以便从handle返回时能够返回到指定的地址上。这个指定的地址其实也在进程的用户栈上,内核又在这个地址上放了几条指令(在栈上放置可执行代码),让进程去调用一个名叫sigreturn的系统调用。

零一万物开放平台
零一万物开放平台

零一万物大模型开放平台

下载

返回到handle函数前的用户栈大致如下:
原有数据 -> 调用sigreturn的指令(设其地址为a) -> 原始返回地址及其调用栈 -> 返回地址(值为a) -> handle的栈变量

内核在handle函数的调用栈上放置sigreturn指令,这是在linux 2.4时的做法。每次调用用户的handle函数都需要向用户栈拷贝这么几条指令,这并不太好。
linux 2.6有一个叫vsyscall page的页面,上面包含了内核为用户程序准备的一些指令,其中就包括调用sigreturn指令。这个vsyscall页被映射到每个进程的虚拟地址空间靠近末尾的部分,被所有用户进程共享,对于用户进程是只读的。这样,handle函数的调用栈上就不需要再塞入sigreturn指令了,直接将handle函数的返回地址设为vsyscall页中对应的代码即可。

为了让handle执行完以后自动调用sigreturn返回内核,内核做了很多事情。那么可不可以约定好,让用户自己去调用sigreturn呢?
当然,这是可以的。只是为了让信号处理机制成为一套完整的机制,内核并没有这么做。否则用户在handle函数里面忘记调用sigreturn的话,可能莫名其妙地进程就崩溃了。而编译器也很难找出这样的错误。

进程调用sigreturn系统调用重新进入内核后,压在用户栈上的原始返回地址及其调用栈被获取。最终内核又会修改栈,让进程返回用户空间时返回到这个原始返回地址上。

本文浅析了linux异步信号handle的方法,包括异步信号的含义、产生、发送、接收、处理和忽略等方面。通过了解和掌握这些知识,我们可以掌握Linux信号处理的核心知识,从而提高系统的稳定性和效率。当然,linux异步信号handle还有很多其他的特性和用法,需要我们不断地学习和研究。希望本文能给你带来一些启发和帮助。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

372

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

563

2023.08.10

磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

1345

2023.06.21

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

700

2023.06.29

linux find
linux find

find是linux命令,它将档案系统内符合 expression 的档案列出来。可以指要档案的名称、类别、时间、大小、权限等不同资讯的组合,只有完全相符的才会被列出来。find根据下列规则判断 path 和 expression,在命令列上第一个 - ( ) , ! 之前的部分为 path,之后的是 expression。还有指DOS 命令 find,Excel 函数 find等。本站专题提供linux find相关教程文章,还有相关

294

2023.06.30

linux修改文件名
linux修改文件名

本专题为大家提供linux修改文件名相关的文章,这些文章可以帮助用户快速轻松地完成文件名的修改工作,大家可以免费体验。

773

2023.07.05

linux系统安装教程
linux系统安装教程

linux系统是一种可以免费使用,自由传播,多用户、多任务、多线程、多CPU的操作系统。本专题提供linux系统安装教程相关的文章,大家可以免费体验。

571

2023.07.06

linux查看文件夹大小
linux查看文件夹大小

Linux是一种自由和开放源码的类Unix操作系统,存在着许多不同的Linux版本,但它们都使用了Linux内核。Linux可安装在各种计算机硬件设备中,比如手机、平板电脑、路由器、视频游戏控制台、台式计算机、大型机和超级计算机。linux怎么查看文件夹大小呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

544

2023.07.20

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

74

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6.4万人学习

Git 教程
Git 教程

共21课时 | 2.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号