Linux--进程信号
前言
无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事情,而不是让烦恼和焦虑毁掉你不就不多的热情和定力。心可以碎,手不能停,该干什么干什么,在崩溃中继续努力前行,这才是一个成年人的素养。
--余华
与大家分享余华老师的名言,希望大家能在学习疲惫时调整好心态,继续砥砺前行!那么今日主题进程信号,以信号的产生-信号的保存-信号的处理为时间线进行讲解,后面也从信号中衍生出来的话题,比如可重入函数,volatile关键字等。
信号入门
信号
信号概念
信号是进程之间事件异步通知的一种方式,属于软中断。
在Linux终端中,通过kill -l查看信号,我们发现信号总数并不是64,它的范围是[1-31]和[34-64]。一般把[1-31]的信号称之为普通信号,[34-64]称之为实时信号。
[hongxin@VM-8-2-centos ~]$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43)
SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47)
SIGRTMIN+13 48)
SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52)
SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57)
SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62)
SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
生活角度的信号
在生活中,我们理解的信号:当一个信号产生时,首先我们知道其意思,并且能产生对应的行为。
举例:红绿灯
1.首先我们能够识别红绿灯,认识它。
我们为什么能够认识信号,这原因是,从小老师的教导,我们记住对红绿灯星号发出后做出相对应的行为。
2.当红绿灯亮起时,红灯停,绿灯行。这是产生行为-走/停。
当绿灯亮起时,我们必须走吗,可以不走,你可以选择下一个的红绿灯,也可以选择跳个舞再走。所以得出一个结论,当信号(随时)产生时,但可以不(立即)执行。
3.当信号产生,时间窗口将它保存后,信号被处理。
如何处理:①可以默认处理(红灯停,绿灯行)②初略处理(当灯亮时,不做出任何行为)③自定义处理(当灯亮时,选择跳舞)。
技术应用角度的信号
将上面的例子和概念迁移到进程中
1.进程的识别:需要先认识(先组织后描述)再产生行为 (处理信号)。
2.进程本身是被程序员编写的属性和逻辑的集合。
3.当进程收到信号时,进程可能正在执行更重要的代码,所以信号不一定会被立即处理。
4.进程本身必须要有对信号的保存能力
5.进程处理信号有三种方式:默认,自定义,忽略【信号被捕捉】
我们知道信号不是被立即处理的,所以信号是需要被保存起来的。那么它是保存在哪里?又是如何保存的呢?
关于信号保存在哪里是不难理解的,因为我们发现信号时发送给进程的,例如我们熟知的kill -9 pid。当进程进入僵尸状态了,我们就可以使用它将其“杀死”。而进程需要识别信号,那么信号是不是应该被保存在PBC(tack_strcut)中的。
对于如何保存,在tack_strcut中建立32位的位图,比特位的位置代表:信号的编号。比特位的内容代表:是否收到信号,0未收到,1收到信号。如图:
发生信号的本质,其实不是发送,而是修改。将位图0置1,进程接受到信号。
谁来维护位图呢?很显然不可能是用户,pbc的数据是不可能让用户随意修改的。只能OS(操作系统),修改位图也只能是OS。
无论未来我们学习多少种信号的发送,本质都是OS向目标进程发送的信号(修改位图)!
回过来,当我们不能直接对PCB进行修改数据,那么当我们发送信号时,OS肯定会提供发送信号处理信号的相关系统调用。
当我们知道信号需要发生,保存,处理。我们可以画出它的生命周期,如图 :
为了更好的观察信号,当用户输入命令,在Shell下启动一个前台进程。用户按下Ctrl-C ,这个键盘输入产生一个硬件中断,被OS获取,解释成信号,发送给目标前台进程 。
前台进程因为收到信号,进而引起进程退出 。代码如下:
#include #include int main() { while(true) { std::cout