目录
一、信号的基本概念
二、信号处理常见方式概览
三、修改信号的响应方式 – signal()
3.1 简单复习结束前台进程
3.2 改变SIGINT信号的响应方式
3.3 自定义方式改变进程对信号的响应
3.4 进程对信号作出两种响应
四、发送信号 – kill()
五、利用信号解决僵死进程问题
一、信号的基本概念
Linux 信号(signals)是一种用于进程间通信(Inter-Process Communication,IPC)的机制,允许进程通过发送和接收信号来通知其他进程某些事件的发生。信号是中断处理的一种手段,可以打断一个进程的正常执行流,迫使它处理特定的事件。与信号有关的系统调用在“signal.h”头文件中有声明 。信号是进程之间事件异步通知的一种方式,属于软中断。每个信号都有一个编号和一个宏定义名称,这些宏定义可以在signal.h中找到,例如其中有定 义 #define SIGINT 2
常用信号
在Linux中,有几种常用的信号:
SIGHUP
(1): 挂起信号,通常用于重新加载配置文件或重启服务。SIGINT
(2): 中断信号,通常由Ctrl+C生成,用于中断进程。SIGQUIT
(3): 退出信号,由Ctrl+\生成,用于退出进程并生成核心转储文件。SIGILL
(4): 非法指令信号,通常由非法指令生成。SIGABRT
(6): 异常终止信号,通常由abort
函数生成。SIGFPE
(8): 浮点异常信号,通常由除零或其他浮点操作错误生成。SIGKILL
(9): 终止信号,不能被忽略或捕获,用于强制终止进程。SIGSEGV
(11): 段错误信号,通常由非法内存访问生成。SIGPIPE
(13): 管道破裂信号,通常在向一个没有读端的管道写数据时生成。SIGALRM
(14): 定时器信号,通常由alarm
函数生成。SIGTERM
(15): 终止信号,用于正常终止进程。SIGUSR1
(10) 和SIGUSR2
(12): 用户自定义信号。- SIGCHLD (17 )子进程结束后,会默认给父进程发送该信号
二、信号处理常见方式概览
一个进程对于信号的响应方式可选的处理动作有以下三种:
- 忽略此信号。
- 执行该信号的默认处理动作。
- 提供一个信号处理函数,要求内核在处理该信号时切换到用户态执行这个处理函数,这种方式称为捕捉 (Catch)一个信号。
signal()的两个参数 第一个是信号代号,第二个是一个函数(参数为int类型,返回值为void)
三、修改信号的响应方式 – signal()
3.1 简单复习结束前台进程
用户输入命令,. 用户按下Ctrl-C ,这个键盘输入产生一个硬件中断,被操作系统获取,解释成信号,发送给目标前台进程 .,前台进程因为收到信号,进而引起进程退出。
注意
- Ctrl-C 产生的信号只能发给前台进程。一个命令后面加个&可以放到后台运行,这样Shell不必等待进程 结束就可以接受新的命令,启动新的进程。
- Shell可以同时运行一个前台进程和任意多个后台进程,只有前台进程才能接到像 Ctrl-C 这种控制键产生的信号。
- 前台进程在运行过程中用户随时可能按下 Ctrl-C 而产生一个信号,也就是说该进程的用户空间代码执行到任何地方都有可能收到 SIGINT 信号而终止,所以信号相对于进程的控制流程来说是异步 (Asynchronous)的。
3.2 改变SIGINT信号的响应方式
SIGINT
(2): 中断信号,通常由Ctrl+C生成,用于中断进程,用户按下Ctrl-C ,这个键盘输入产生一个硬件中断,被操作系统获取,解释成信号,发送给目标前台进程 .,前台进程因为收到信号,进而引起进程退出。这里我们利用signal()系统调用改变它的响应方式为忽略。
3.3 自定义方式改变进程对信号的响应
3.4 进程对信号作出两种响应
四、发送信号 – kill()
kill() 可以向指定的进程发送指定的信号:
五、利用信号解决僵死进程问题
进程复制与替换一章讲过用wait函数清理僵尸进程,父进程可以阻塞等待子进程结束,也可以非阻塞地查询是否有子进程结束等待清理(也就是轮询的方式)。采用第一种方式,父进程阻塞了就不 能处理自己的工作了;采用第二种方式,父进程在处理自己的工作的同时还要记得时不时地轮询一下,程序实现复杂。 其实,子进程在终止时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号 的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。
请编写一个程序完成以下功能:父进程fork出子进程,子进程调用exit(0)终止,父进程自定义SIGCHLD信号的处理函数, 在其中调用wait获得子进程的退出状态并打印。 事实上,由于UNIX 的历史原因,要想不产生僵尸进程还有另外一种办法:父进程调 用signal将SIGCHLD的处理动作置为SIG_IGN,这样fork出来的子进程在终止时会自动清理掉,不会产生僵尸进程,也不会通知父进程。系统默认的忽略动作和用户用signal函数自定义的忽略通常是没有区别的,但这是一个特例。此方法对于Linux可用,但不保证 在其它UNIX系统上都可用。
以上就是全部内容!请务必掌握,这是后续学习的基础,欢迎大家点赞加关注评论,您的支持是我前进最大的动力!下期再见!