信号在最早的Unix系统中被引入,内核可用信号通知进程系统所发生的事件。在现实生活中,我们每天都在接触信号,下课铃声、红绿灯、闹钟等都是信号。
信号的本质
操作系统给进程发送信号,本质上是给进程的PCB中写入数据,修改相应的PCB字段,进程在合适的时间去处理所接受的信号。我们模拟一下这样的场景:
(1)用户输入一个命令,在shell下启动一个前台进程;
(2)用户按下Ctrl+c,通过键盘输入产生一个硬件中断;
(3)如果CPU当前正在运行此进程的代码,则该进程的用户空间的代码将暂停执行,CPU从用户态切换至内核态处理中断;
(4)终端驱动程序将Ctrl+c解释为一个SIGINT信号,记在该进程的PCB中;
(5)当某个时刻从内核返回至该进程的用户空间代码继续执行之前,首先处理PCB中记录的信号;SIGINT信号的默认处理动作为终止信号,所以直接终止进程而不再返回到它的用户空间代码;
注:Ctrl+c所产生的信号只能发送给前台进程,如果想让该进程在后台运行,需要在启动该进程的时候,在后面加上&,这样shell就不必等待进程结束就可以接受新的命令,启动新的进程。
上图中,S为后台进程,S+为前台进程;shell可以同时运行一个前台进程和任意多个后台进程,只有前台进程才能接受诸如Ctrl+c这样的信号,前台进程在运行过程中用户随时按下Ctrl+c而产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能接收到一个SIGINT信号而被终止,因此信号相对于进程的控制流程来说是异步的。
普通信号与实时信号
我们使用 kill -l 命令可以查看系统定义的信号列表,每个编号都有一个宏与之对应,可以在 /usr/include/asm/signal.h 中查看,下图中 1~31号为普通信号,34~36号信号为实时信号。
那么使用上述信号的目的是什么呢?大致可以总结为两点。
ÿ