linux 信号机制

本文旨在弄懂linux中的信号工作原理

1 查看所有信号

kill -l 命令可以查看linux下所有信号

linux 信号机制

2 信号产生

2.1 用户在终端按下某些键时,终端驱动程序会发送信号给前台进程

例如Ctrl-C产生SIGINT信号,Ctrl-\产生SIGQUIT信号,Ctrl-Z产生SIGTSTP信号

2.2 硬件异常产生信号,这些条件由硬件检测到并通知内核,然后内核向当前进程发送适当的信号

例如当前进程执行了除以0的指令,CPU的运算单元会产生异常,内核将这个异常解释为SIGFPE信号发送给进程。再比如当前进程访问了非法内存地址,,MMU会产生异常,内核将这个异常解释为SIGSEGV信号发送给进程

2.3 一个进程调用kill(2)函数可以发送信号给另一个进程

2.4 可以用kill(1)命令发送信号给某个进程,kill(1)命令也是调用kill(2)函数实现的,如果不明确指定信号则发送SIGTERM信号,该信号的默认处理动作是终止进程

2.5 当内核检测到某种软件条件发生时也可以通过信号通知进程,例如闹钟超时产生SIGALRM信号,向读端已关闭的管道写数据时产生SIGPIPE信号

关于调用函数向进程发送信号

#include <signal.h>
int kill(pid_t pid, int signo);
int raise(int signo);

上面的两个函数,我们来解释一下, 
kill函数两个参数,pid为给哪个进程要发信号,signo为哪中信号。 
raise函数其实是kill函数的封装,raise函数是自己给自己发送任意信号。 
上面两个函数都是成功返回1,失败返回0

3 信号的阻塞

信号产生时,内核在该进程控制块PCB中设置该信号的未决标志,直到信号递达才清除该标志。 信号在内核中的示意图 

linux 信号机制

信号递达(Delivery):实际执行信号的处理动作

信号未决(pending):信号从产生到递达之间的状态

信号阻塞(block):产生信号,信号也不会被递达。被阻塞的信号产生时将保持在未决状态,信号被阻塞了就不被递达。 
未决和阻塞标志可以用相同的数据类型sigset_t存储,sigset_t称为信号集

进程可以选择阻塞某个信号 如果在信号未决后,我们设置了阻塞,那么该信号会在未决表中等待解除阻塞 在信号中我们要明白,信号的阻塞和忽略不同,忽略是信号的处理方式,而阻塞只是信号在传递过程中,对信号的一种延后处理的行为。

信号未阻塞也未产生,当它递达时执行默认处理动作

信号产生但被阻塞,所以暂时不能递达。尽管处理动作是忽略,但是在解除阻塞之前还不能忽略该信号,因为进程仍有机会改变对信号的处理动作之后再解除阻塞

4 信号处理

忽略:忽略此信号。

默认:执行该信号的默认处理动作 自定义捕捉。

捕捉:提供一个信号处理函数,要求内核在处理信号时切换到用户态执行这个处理函数。

 

 

 

参考

https://blog.csdn.net/gangstudyit/article/details/80551912

https://blog.csdn.net/xs_520/article/details/73250923