【Linux学习】信号 | 您所在的位置:网站首页 › 核心转储文件有哪些 › 【Linux学习】信号 |
🐱作者:一只大喵咪1201 🐱专栏:《Linux学习》 🔥格言:你只管努力,剩下的交给时间! 从生活中入手,例如发令枪,闹钟,红绿灯等等,这些都是信号。信号必须都是动态的,像路标就不能称之为信号。 以红绿灯为例,一看到红绿灯我们就知道红灯行,绿灯停,我们不仅能认识它是一个红绿灯,而且还知道应该产生什么样的行为,这样才算是能够识别红绿灯。 识别 = 认识 + 行为产生对于红绿等这个信号,我们需要有如下几个共识: 我们之所以能识别红绿灯,是因为我们受到过教育(手段),让我们在大脑中记住了不同颜色对应的行为(属性)。当绿灯亮了以后,不一定要立刻过马路,比如有其他的车闯红灯,需要进行避让,所以说我们不一定要立刻产生相应的行为。红灯亮了以后,正好来了一个电话,在接电话这个期间我们会记住此时是红灯,不会将这个状态忘记。红绿灯默认的行为是红灯行,绿灯停,但是也可以产生其他行为,还可以忽略。现在将生活中红绿灯的例子迁移到进程中: 共识:信号是发给进程的。 进程之所以能够识别信号,是因为程序员将对应的信号种类和逻辑已经写好了的。当信号发给进程后,进程不一定要立刻去处理,可能有更加紧急的任务,会在合适的时候去处理。进程收到信号到处理信号之前会有一个窗口期,这个期间要将收到的信号进行保存。处理信号的方式有三种:默认动作,自定义动作,忽略。
进程能够识别的信号是已经写好的,它有62个: 这其中没有32号和33号信号,所以一共有62个信号。而且这里我们只学习普通信号,对实时信号暂不做研究。 在使用这些信号时,可以用信号名,也可以用信号编号,它是一样的,都是宏定义后的结果。根据我们对Linux的了解,信号存放在哪里呢?既然信号是给进程的,而进程是通过内核数据结构来管理的,所以我们可以推断出,信号放在进程的task_struct结构体中。 既然它是在PCB中,而且数量是31个,task_struct中必定不会设置31个变量来存放信号,数组还有可能,但是信号的状态只分为有和没有两种,所以再次推断,31个信号放在一个32位的整形变量中,每个比特位代表一个信号。 本喵写一段伪代码来示意一下: struct task_struct { //进程属性 unsigned int signal; //....... }就像在学习基础IO和进程间通信的时候,那些flags标志中的不同的比特位代表着不同的意义,这31个信号量也是这种方式: 具体的保存细节后面本喵再详细讲解。 问题来了,内核数据结构的修改,这个工作是由谁来完成的?毫无疑问是操作系统,因为task_struct就是它维护的,而且是存在于内存中的,只有操作系统才有权力去修改它,用户是无法直接操作的,因为操作系统不相信任何人。 所以说,无论哪个信号,最后的本质都是由操作系统发生给进程的,这里的发送本质就是在修改task_struct中存放信号那个变量的比特位。 信号发送的本质就是在修改PCB中的信号位图。无论未来我们学习了多少中发送信号的方式,本质都是通过操作系统向目标进程发送信号。 所以操作系统一定会提供相关的系统调用,比如我们之前使用过的各自信号: kill -9 pid值 //停止某个进程 kill -19 pid值 //暂停某个进程 kill -18 pid值 //继续某个进程它们的底层一定是在调用相关的系统调用,来让操作系统修改PCB中的信号位图。 🎵信号处理方法的注册 所谓的注册,就是告诉操作系统,当某个进程接收到某个信号后的处理方式。既然是告诉操作系统,那么肯定会用到系统调用,该系统调用的名字是signal(): 可以将信号的处理方式写成一个函数,然后将函数名传递个signal,此时当进程接收到signum指定的信号编号时,就会执行我们定义的函数。 void handler(int signo) { cout |
CopyRight 2018-2019 实验室设备网 版权所有 |