linux信号处理相关知识

时间:2023-12-23 21:16:19
 

因为要处理最近项目中碰上的多个子进程退出信号同时到达,导致程序不当产生core的情况,今天我花了时间看了一些关于linux信号处理的博客。

总结一下:(知识未经实践)

  linux信号分两种,一种实时信号(也叫可靠信号),一种非实时信号(也叫不可靠信号)。
实时信号之所以是可靠的,因为在进程阻塞该信号的时间内,发给该进程的所有实时信号会排队,而非实时信号则会合并为一个信号。(可以这样理解,同一个不可靠信号同时产生时,只有一个信号会被处理,其它的丢弃)
早期设计的信号都是不可靠的,我们常见的SIGUSR1、SIGCHILD、SIGINT只有SIGRTMIN(信号值为34)以后的信号才是可靠的。
因此,当我们收到多个子进程同时退出的SIGCHLD信号时,最好循环调用waitpid,直到确认所以子进程退出已被处理,否则可能导致某些子进程成为僵尸进程
信号是可以忽略、捕获或阻塞的,但SIGSTOP和SIGKILL都是不可忽略、捕获或阻塞的信号。另外有一些错误信号是不可阻塞的,如SIGFPE、SIGILL、SIGSEGV、SIGBUS。
信号捕获处理有两种方式,一种是异步处理,另一种也是异步处理。(开玩笑的,另一种是同步处理)我们比较常用的是异步处理方式,即:注册一个信号处理函数,在信号发生时由内核调用。
异步处理方法需要注意注册的信号处理函数要尽量短,并且不可以调用非可重入函数(如printf、malloc、大多数使用使用了全局或静态数据结构的函数)。
注意非可重入函数并非线程安全函数,两者概念不一样。一般线程安全函数都是通过使用锁来达到线程安全的,但如果在信号处理函数里面这样做,很容易导致死锁。(当获取锁之后,未释放之前又发生信号函数调用即会出现)
如果你处理某个信号里需要消耗比较长的时间,一种推荐的处理方式是在消息处理函数将该信号登记到某个处理队列后立即返回,在主进程函数里面顺序处理。
接上,在c语言里面,可以在信号函数里面,使用write函数将信号值写入一个管道。管道另一端使用select监听处理。具体可以参考libevent
信号是线程级的,你可以使用pthread_kill向特定某个线程发送信号。如果你使用kill函数往某个进程发送信号,内核会随机将信号发给一个未阻塞该信号的线程处理。
在多线程应用中,我们需要使用sigaction来代替singal函数,并且可以使用pthread_sigmask来为每个线程设置独立的信号掩码。
多线程应用中,有一种同步处理信号的方式:开辟一个线程专门负责处理信号,其它线程把信号都屏蔽掉。信号处理线程循环调用sigwait等待信号到来并处理。

(直接粘贴文字变成一行,所以使用插入代码的方式)

14 Linux支持的信号列表如下。很多信号是与机器的体系结构相关的

信号值 默认处理动作 发出信号的原因

SIGHUP 1 A 终端挂起或者控制进程终止

SIGINT 2 A 键盘中断(如break键被按下)

SIGQUIT 3 C 键盘的退出键被按下

SIGILL 4 C 非法指令

SIGABRT 6 C 由abort(3)发出的退出指令

SIGFPE 8 C 浮点异常

SIGKILL 9 AEF Kill信号

SIGSEGV 11 C 无效的内存引用

SIGPIPE 13 A 管道破裂: 写一个没有读端口的管道

SIGALRM 14 A 由alarm(2)发出的信号

SIGTERM 15 A 终止信号

SIGUSR1 30,10,16 A 用户自定义信号1

SIGUSR2 31,12,17 A 用户自定义信号2

SIGCHLD 20,17,18 B 子进程结束信号

SIGCONT 19,18,25 进程继续(曾被停止的进程)

SIGSTOP 17,19,23 DEF 终止进程

SIGTSTP 18,20,24 D 控制终端(tty)上按下停止键

SIGTTIN 21,21,26 D 后台进程企图从控制终端读

SIGTTOU 22,22,27 D 后台进程企图从控制终端写

处理动作一项中的字母含义如下

A 缺省的动作是终止进程

B 缺省的动作是忽略此信号,将该信号丢弃,不做处理

C 缺省的动作是终止进程并进行内核映像转储(dump core),内核映像转储是指将进程数据在内存的映像和进程在内核结构中的部分内容以一定格式转储到文件系统,并且进程退出执行,这样做的好处是为程序员提供了方便,使得他们可以得到进程当时执行时的数据值,允许他们确定转储的原因,并且可以调试他们的程序。

D 缺省的动作是停止进程,进入停止状况以后还能重新进行下去,一般是在调试的过程中(例如ptrace系统调用)

E 信号不能被捕获

F 信号不能被忽略

参考文章:
https://www.cnblogs.com/WangBoBlog/p/8081284.html Linux 的信号和线程
https://blog.csdn.net/xwc583413343/article/details/55106337 信号注册函数回收子进程,waitpid非阻塞回收
https://blog.csdn.net/hacode/article/details/43483057 Linux 实时信号程序中锁的探索
https://blog.csdn.net/yusiguyuan/article/details/14229017 Linux 多线程应用中如何编写安全的信号处理函数
https://www.cnblogs.com/hoys/archive/2012/08/19/2646377.html Linux信号(signal) 机制分析