1.如果信号的处理动作是用户自定义函数, 在信号递达时就调用这个函数, 这称为捕捉信号
1.用户程序注册了SIGQUIT信号的处理函数sighandler。
2.当前正在执行 main函数, 这时发生中断或异常切换到内核
3.在中断处理完毕后要返回用户态的main函数之前检查到有信号SIGQUIT递达
4.内核决定返回用户态后不是恢复main函数的上下文继续执行,而是执行sighandler函数,sighandler和 main函数使用不同的堆栈空间, 它们之间不存在调用和被调用的关系, 是两个独立的控制流程
5.sighandler函数返回后自动执行特殊的系统调用sigreturn再次进入内核态
6.如果么有新的信号递达,这次再返回用户态就是回复main函数的上下文继续执行了
2.sigaction
函数原型 ; #include <signal.h>
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
作用 ; sigaction函数可以读取和修改与指定信号相关联的处理动作。
返回值 ; 成功返回0, 出错返回 -1
signo : 指定的信号的编号。
若act指针非空, 则根据act修改该信号的处理动作。
若oact指针非空,则通过oact传出该信号原来的处理动作。
act 和 oact 指向sigaction结构体
struct sigaction {
void (*sa_handler)(int); // 信号处理函数
sigset_t sa_mask; // 临时信号屏蔽字
int sa_flags; // 解释在下面
voi (*sa_sigaction)(int , siginfo_t *, void *); // 带参数的信号处理函数
};
当 sa_flags = 0时, 调用信号处理函数。
当sa_flags = SA_SIGINFO 时, 使用带参数的信号处理函数
将sa_handler赋值位常数 : SIG_IGN 表示忽略信号
赋值为 : SIG_DFL 表示执行系统默认动作
3.pause 使调用进程挂起直到信号递达
函数原型 : #include <unistd.h>
int pause(void);
若信号的处理动作是终止进程则进程终止, 么有机会返回
若信号的处理动作是忽略,则进程继续处于挂起状态,不返回
若信号的处理动作是捕捉, 则调用了信号处理函数后, 返回-1.error设置为 EINTR
pause只有出错的返回值。 EINIT 表示“信号被中断”
4.一般情况下, 调用信号处理函数时,信号自动屏蔽。
5.注意 : 信号处理函数不可不注册, 不注册的话,会按照默认方式处理 : 结束进程
6.不可重入 :
1.使用全局或静态变量
2.不使用标准输入和标准输出
3.不使用临界区变量
7. 如果一个函数符合以下条件之一则是不可重入的 :
调用了malloc或free, 因为maloc也是用全局链表来管理堆的
调用了标准I/O库函数,标准I/O库的很多实现都以不可重入的方式使用全局数据结构
8.sig_atomic_t 类型 : 原子类型
volatile限定符
volatile限定 :
变量的内存单元中的数据不需要写操作就可以自己发生变化,每次读上来的值都可能不一样
即使多次向变量的内存单元中写数据,只写不读也并不是在做无用功,而是有特殊意义的
sig_aomic_t类型的变量应该总是加上volatile限定符
9.竟态条件与 sigsuspend函数
竟态条件 : 如果我们写程序时考虑不周密,就可能由于时序问题而导致错误
函数原型 : #include <signal.h>
int sigsuspend(const sigset_t * sigmask);