【Linux取经之路】进程信号的产生
前言
关于信号,考虑到直接把信号的产生、保存和处理都放在一篇的话,篇幅很长,也容易影响到读者的阅读体验,所以呢我打算分两到三篇来写。第一篇,先来谈谈信号的产生。
信号的概念
我们来看看信号的概念。
在Linux操作系统中,信号(Signal)是一种重要的机制,它用于通知进程发生的事件和状态变化。
单看概念,太抽象了。下面举个例子:在中学阶段,我们常常听到的一句话就是——铃声就是命令。学校下课铃声响了,我们知道可以从上课的专注状态切换到休息状态了。这个例子中的铃声就是一个信号,我们就是一个个的进程,学校就相当于操作系统。对,信号是由操作系统发给进程的。并且,在操作系统把信号发给进程之前,进程就已经知道如何处理该信号了。是不是有点奇怪?你想想,在下课铃声没响之前,我们是不是已经知道下课铃响了我们可以做什么?也就是说,我们自身内置了下课铃响了的处理办法。进程也一样,它的PCB也内置了一些信号的处理方法。下面我们来看看操作系统定义的信号列表。
操作系统定义的信号列表
命令:kill -l
其中,1到31号信号为普通信号,34到64号信号为实时信号。你可能会问——32和33号信号去哪了?这两个编号可能保留或者未使用。这里我们只谈普通信号。光看这堆信号没意思,我们挑一个常用的信号来讲一讲顺便引出操作系统是如何给进程传递信号的。
9号信号——SIGKILL:强制终止一个进程,用法为kill -9 进程pid。 它的操作比较见到,我就不演示了。下面我们谈谈操作系统是如何给进程发送信号的。
先说结论:操作系统是通过修改进程PCB内的位图来将信号发送给进程的。
下面解释:1到31号信息,操作系统可以使用一个32个比特位的位图来表示。第一位对应的就是1号信号,第二位对应2号信号……每一个比特位上无非两种情况,要么是0要么是1。例如,第9个比特位的值为1,表示操作系统给该进程发送了9号信号,如果对应比特位为0,则说明没有收到操作系统发送的信号。下图就是上面提到的PCB内的位图。
所以说,操作系统给进程发信号其实是在修改PCB内的位图,发送信号只是一个形象的说法。
信号产生的几种方式
一、通过终端按键产生信号
下面通过几个常用的键盘组合键来说明。
Ctrl + c:结束一个进程。如果Ctrl + c 没能成功结束掉一个进程,那么说明这个进程是在后台执行,需要使用Ctrl + \,Ctrl + c只能结束掉前台进程。这些组合键本质上就是在给进程发送信号。当我们按下 Ctrl+C 组合键时,操作系统会捕获这个按键事件,并向当前的前台进程发送一个SIGINT 信号。这个信号告诉进程需要立即停止当前的执行。
二、调用系统函数向进程发送信号
我们常用 kill -9 pid干掉一个进程,kill命令会调用kill函数来向指定进程发送信号。
三、硬件异常产生信号
当硬件检测到某些异常条件时,会通知内核,然后内核向当前进程发送适当的信号。例如,除零错误会产生SIGFPE信号,空指针解引用会产生SIGSEGV信号。
四、软件条件产生信号
管道操作:在使用管道进行进程间通信时,如果读端文件描述符被关闭,而写端仍然尝试写入数据,就会触发SIGPIPE信号。
闹钟函数:通过调用alarm函数可以设置一个闹钟,当闹钟超时后,内核会向当前进程发送SIGALRM信号。
下面我们来介绍一下alarm这个函数。
alarm函数的功能是设置一个定时器(也称为闹钟),在指定的秒数后,内核会向当前进程发送一个SIGALRM信号。这个SIGALRM信号的默认行为就是结束掉当前进程。下面写几行代码使用一下alarm函数。
本文到这就结束啦~如有错误,请不吝指出!
原文地址:https://blog.csdn.net/bit_pan/article/details/143700022
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!