linux信号处理
信号在内核中的表示
- 递达(Delivery):执行信号的动作
- 未决(Pending):被阻塞的信号处在的状态,信号从产生到递达之间的状态
- 阻塞(Block):可以理解为屏蔽信号,一个信号可以若被阻塞,它将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。
注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作
sigset_t信号集、信号集操作函数
未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态,,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask),这里的“屏蔽”应该理解为阻塞而不是忽略。
信号集操作函数
#include <signal.h>
int sigemptyset(sigset_t *set);/* Clear all signals from SET. 清空信号集*/
int sigfillset(sigset_t *set);// 把所有信号的对应bit置位=把64种信号都放入信号集(没有32 33) /* Set all signals in SET. */
int sigaddset(sigset_t *set, int signo);// 增加某个指定信号
int sigdelset(sigset_t *set, int signo);//删除某个指定信号
int sigismember(const sigset_t *set, int signo);// 查看信号是否在集合里面 /* Return 1 if SIGNO is in SET, 0 if not. */
注意,在使用sigset_t类型的变量之前,一定要调用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效信号。上面四个函数都是成功返回0,出错返回-1。sigismember是一个布尔函数,用于判断一个信号集的有效信号中是否包含某种信号,若包含则返回1,不包含则返回0,出错返回-1。
sigprocmask
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
//功能:读取或更改进程的信号屏蔽字。 (sigset_t)
//返回值:若成功则为0,若出错则为-1
/*
如果oldset是非空指针,则读取进程的当前信号屏蔽字通过oldset参数传出。
如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。
如果oldset和set都是非空指针,则先将原来的信号屏蔽字备份到oldset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下表说明了how参数的可选值:
SIG_BLOCK:set信号集包含了我们希望添加到当前进程使用的信号屏蔽字中
SIG_UNBLOCK:set信号集包含了我们希望从当前进程使用的信号屏蔽字中接触阻塞的信号
SIG_SETMARK:设置当前信息屏蔽字为set
*/
sigpending
#include <signal.h>
int sigpending(sigset_t *set);
//功能: sigpending读取当前进程的未决信号集,也就是获得当前已递送到进程,却被阻塞的所有信号,通过set参数传出。
//返回值:若成功则为0,若出错则为-1
sigwait
//sigwait的含义就如同它的字面意思:等待某个信号的到来。 如果 调用该函数的线程没有等到它想等待的信号那么该线程就休眠。