Linux - 信号

参考文档

常见信号

SIGKILL:不可被捕获、忽略,取值为9
SIGINT:可以被捕获、忽略、阻塞,取值为2,由ctrl+c产生
SIGTERM:可以被捕获、忽略、阻塞,kill命令默认发这个信号
SIGQUIT):类似SIGINT,由ctrl+\产生
SIGSTOP:不可被忽略、捕获,停止程序
SIGSTP:可以被捕获、忽略、阻塞,由ctrl+z产生
SIGCONT:恢复进程的执行,不能被捕获或忽略

同步/异步信号

同步信号的例子包括非法存储器访问以及除法除以0.如果一个正在运行的程序执行了任一操作,一个信号就会生成。

同步信号传递到执行操作而导致产生信号的同一进程(这就是被认为是同步的原因)

当一个信号由运行的进程之外的事件产生,那么进程就会异步的接收这个信号。这样的例子包括用特定的击键结束进程(比如ctrl + c)或者是定时器到期。通常,信号被发送到另一个进程

信号的响应

在进程由内核态返回用户态时,会在在内核态检查当前是否有信号待处理,如果有的话,就会进入信号响应流程

多线程环境下信号传递

单线程程序的信号处理比较直接,信号总是发给进程。
不过,对于多线程程序,发送信号比较复杂,因为进程可能有多个线程,应该将信号发给谁呢??
一般来说,存在以下选项:

  1. 将信号发送到信号所应用的线程。
  2. 将信号传递到进程中的每个线程。
  3. 将信号传递给进程中的某些线程。
  4. 指定一个特定的线程来接收该进程的所有信号。

传递信号的方法取决于所产生的信号的类型。例如,需要将同步信号传递给引起信号的线程,而不需要传递给进程中的其他线程。然而,对于异步信号,情况就不那么清楚。一些异步信号——例如终止进程的信号(例如ctrl + c)——应该发送到所有线程。

发送信号的标准UNIX函数是:

1
kill(pid t pid, int signal)

该函数指定哪个特定的信号(即signal参数)被发送到指定的进程上(即pid参数)。大多数多线程版本的UNIX允许一个线程指定它将接受哪个信号,它将会阻止哪个信号。因此,在某些情况下,异步信号只能传递给那些没有阻止它的线程。但是,因为信号只需要处理一次,所以信号通常只发送到发现的第一个不阻止它的线程上[但是不可捕获、忽略的信号会被发送给每一个线程并执行]。POSIX Pthreads提供了以下功能,它允许将信号传递到指定的线程(tid):

1
pthread_kill(pthread t tid, int signal)

使用指南

线程的信号屏蔽字是per_thread的,因此通过信号屏蔽关键字,只有一个线程没有屏蔽该信号,其它线程均屏蔽该信号。达到控制某个线程处理某个信号的目的。
但是对于那些不能被屏蔽的信号怎么办?


Linux - 信号
http://example.com/2024/09/07/操作系统/Linux - 信号/
作者
Cyokeo
发布于
2024年9月7日
许可协议