生活中的信号举例:红绿灯、铃声、闹钟、旗语
我们是如何得知这些生活中的信号的呢?需要有人教我们认识这些场景下的信号以及所表示的含义,也就是说我们要能够识别这些信号。
我们收到对应的信号时要做什么?其实我们早就知道了信号产生之后要做什么,即便当前信号还没有产生,也就是说我们已经提前知道了对应信号的处理办法。
总结:
1.要具备处理信号的能力有两个前提条件:(1)在信号还没产生时就能够识别这些信号(2)在信号还没产生时已经提前知道这个信号的处理办法。
在生活中要提前具备处理信号的能力(在信号还没产生时就能够识别和处理这些信号),需要社会教我们。
2.在计算机领域,信号是给进程发送的,进程要具备处理信号的能力,也有两个前提条件:(1)提前已经具备了能够识别这些信号的能力(2)提前已经具备了对应信号的处理办法。
在计算机系统中,进程要提前具备处理信号的能力(提前已经具备了能够识别和处理这些信号的能力),需要程序员在操作系统中内置了相关代码,操作系统来帮我们教进程。
因此对于进程来说,即便信号还没有产生,进程已经具有了识别和处理对应信号的能力。
用户输入命令,在Shell下启动一个前台进程,用户按下Ctrl C ,被操作系统获取并解释成信号,发送给目标前台进程,前台进程因为收到信号,进而引起进程退出。 代码验证:创建myproc.cc文件,写入下图一所示的代码,创建makefile文件,写如下图二所示的代码,使用make命令生成myproc可执行程序。
如果使用./myproc命令运行myproc可执行程序,运行起来后myproc是一个前台进程,使用ctrl c即可终止该进程,如下图三所示。
如果使用./myproc &命令运行myproc可执行程序,运行起来后myproc是一个后台进程,如下图四所示,可以看到运行后打印了一个[1] 17344,此时使用ctrl c无法终止该进程,要想终止该进程,可以使用kill命令该进程杀死(前面讲过),也可以先使用jobs命令查看对应进程任务编号,然后使用fg 1命令将对应1号后台进程任务放到前台,此时myproc进程是一个前台进程,使用ctrl c即可终止该进程。
![]()
注:
1.前后端混打的时候缺乏访问控制,如上图四所示,后端进程的打印会将我们的输入内容打乱,显示器中我们输入内容后虽然显示出来是乱的,但在底层其实并不会干扰到我们的输入内容。
2.如果使用 fg+任务号 命令将对应的任务放到前台后,又想将该任务放回到后台,那么先ctrl z然后使用jobs命令,可以看到对应的任务进程已经被放到了后台,但是此时该任务进程处于stopped暂停状态,使用 bg+任务号 命令再次将对应任务进程运行起来,如下图所示。
3.Ctrl C 产生的信号只能发给前台进程。一个命令后面加个&可以放到后台运行,这样Shell不必等待进程结束就可以接受新的命令,启动新的进程。 Shell可以同时运行一个前台进程和任意多个后台进程,只有前台进程才能接到像 Ctrl C 这种控制键产生的信号。
前台进程在运行过程中用户随时可能按下 Ctrl C 而产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能收到 SIGINT 信号而终止,所以信号相对于进程的控制流程来说是异步(Asynchronous)的。
使用 kill -l 命令可以察看系统定义的信号列表,如下图所示。
注:
1.每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到,例如其中有定义 #define SIGINT 2。 2.从上图可以看出没有0、32、33号信号,以32、33号为界信号被分为了两批。编号1-31我们称为普通信号,编号34-64是实时信号,本篇只讨论编号为1-31的信号,不讨论实时信号。这些信号各自在什么条件下产生,默认的处理动作是什么,在signal(7)中都有详细说明:man 7 signal。
信号的处理,可选的处理动作有以下三种: 1.执行该信号的默认处理动作。 2. 忽略此信号。 3. 提供一个信号处理函数,要求内核在处理该信号时切换到用户态执行这个处理函数,这种方式称为捕捉一个信号。2.信号产生的一般方式注:因为信号产生是异步的(信号随时都可能产生),当信号产生的时候,对应的进程可能正在做更重要的事情,该进程可以暂时不处理这个信号。因此当一个进程收到信号时,该进程可能不需要立即处理这个信号,这里不需要立即处理信号不代表这个信号不会被处理,进程需要记住这个待处理信号。
3.信号递达和阻塞
4.握信号捕捉的一般方式