之前我们学习了信号递达和阻塞的基本概念和原理,而今天我们将继续学习信号。
本文我们的目标是:
1、掌握信号捕捉的一般方式
2、了解可重入函数的概念
3、了解竞态条件的情景和处理方式
4、了解SIGCHLD信号,重新编写信号处理函数的一般处理机制
首先我们先来看一下信号捕捉的一般方式。之前我们提到过信号处理的几个常见的方式:
1、忽略此信号
2、执行该信号的默认处理动作
3、提供一个信号处理函数,要求内核在函数处理该信号时切换到用户态执行这个函数,我们称这种方式为捕捉(Catch)一个
信号
了解了捕捉的基本概念,那么我们现在来看一下:
1、内核是如何实现信号的捕捉的?
如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用
户空间的。处理过程比较复杂。
内核实现信号捕捉的步骤:
1、用户为某信号注册一个信号处理函数sighandler。
2、当前正在执行主程序,这时候因为中断、异常或系统调用进入内核态。
3、在处理完异常要返回用户态的主程序之前,检查到有信号未处理,并发现该信号需要按照用户自定义的函数来处理。
4、内核决定返回用户态执行sighandler函数,而不是恢复main函数的上下文继续执行!(sighandler和main函数使用的是
不同的堆栈空间,它们之间不存在调用和被调用的关系,是两个独立的控制流程)
5、sighandler函数返回后,执行特殊的系统调用sigreturn从用户态回到内核态6、检查是否还有其它信号需要递达,如果没有 则返回用户态并恢复主程序的上下文信息继续执行。
2、sigaction
#include <signal.h>
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
处理方式:
1、若act指针非空,则根据act结构体中的信号处理函数来修改该信号的处理动作。
2、若oact指针非空,则通过oact传出该信号原来的处理动作。
3、现将原来的处理动作备份到oact里,然后根据act修改该信号的处理动作。
sigaction函数可以读取和修改与指定信号相关联的处理动作。调用成功则返回0,出错则返回-1。act和oact指向sigaction结构体。
(注:后两个参数都是输入输出型参数!)
将sa_handler三种可选方式: