SIGSEGV 由“kill”生成时是否特殊?

Dim*_*ima 2 c++ posix signals kill segmentation-fault

我知道SIGSEGV当内核使用它报告内存访问冲突时不能忽略这一点。但是,如果我安装一个SIGSEGV不执行任何操作的信号处理程序,然后另一个进程使用kill该信号向我发送该信号,那么其行为是否与我使用“正常”信号(如 )相同SIGUSR1?

zwo*_*wol 5

Grjesh Chauhan 的答案在技术上是正确的,但很难理解,所以我将写出我自己对基本相同点的阐述。带脚注。0

\n\n

Dima 询问当一个线程安装了一个不执行任何操作的处理程序SIGSEGV,然后另一个线程使用kill1在该线程上生成时会发生什么SIGSEGV。一句话的答案是处理程序运行,不执行任何操作,然后控制权返回到中断线程内的正常流程。与内核生成SIGSEGV对实际内存访问冲突的响应不同,这种情况不会触发未定义的行为2。SIGSEGV然而,和它的朋友(SIGBUS、SIGFPE、 和)的预期目的SIGILL是让内核告诉你的程序它做了一些令人发指的事情,肯定有一个bug,正常执行无法继续,你想在之前清理一下吗你被杀了吗?因此,将它们用于其他用途是不明智的。为每个应用程序保留了几个信号(SIGUSR1、SIGUSR2和SIGRTMINthrough SIGRTMAX),以供其随意使用;你应该使用其中之一。

\n\n
\n\n

对于更长的答案,我将抄袭 POSIX 标准的3小节Signal Actions。首先,四个信号SIGFPE、SIGILL、SIGSEGV和SIGBUS,像任何其他信号一样,可以在没有特定时间的情况下“异步”传递\xe2\x80\x94,因为某些代码使用系统调用(例如kill)来生成他们。当发生这种情况时,它们的处理方式与任何其他信号完全相同,其默认“操作”恰好是“异常终止程序”;请注意,许多其他信号也具有此属性,包括保留供应用程序使用的信号。如果你的程序只需要担心接收SIGFPE, SIGILL, SIGSEGV, ,并且SIGBUS当它们由 和 朋友生成时kill,它可以用它们做所有正常的事情:阻止它们,忽略它们,建立信号处理程序来执行对某个有效的任何事情。异步信号处理程序,4sigwait通过或signalfd而不是正常的异步系统陷阱式传递机制接收它们。

\n\n

然而。 SIGFPE、SIGILL、SIGSEGV和SIGBUS也由内核“同步”生成,以响应触发硬件异常的不同类型的错误程序行为,例如尝试访问未映射的内存。同步意味着信号在执行有问题的 CPU 指令后立即传递,并且是在同一线程上,而不是进程中碰巧解除阻塞的任何线程上。我们真的不是在开玩笑“立即”部分:如果有一个信号处理程序,那么当它执行时,保存的程序计数器将指向导致任何类型的硬件异常的确切指令。内核不允许执行导致 CPU 发出硬件异常的指令,因此 POSIX 表示尝试丢弃这些信号,而不是终止进程或采取一些激烈的恢复操作:

\n\n
\n

SIGFPE当进程忽略不是由、SIGILL、SIGSEGV或SIGBUS生成的kill()、sigqueue()、 或信号后,进程的行为是未定义的raise()。

\n
\n\n

(上下文中的“忽略之后”意味着“当操作设置为 时,如果内核尝试同步生成这些信号之一SIG_IGN。)

\n\n
\n

对于不是由kill()、sigqueue() 或raise() 生成的SIGBUS、SIGFPE、SIGILL 或SIGSEGV 信号,进程从信号捕获函数正常返回后,进程的行为是未定义的。

\n
\n\n

(“正常返回”意味着“不是通过调用(sig)longjmp”。至少就内核而言,展开堆栈并在其他地方恢复执行是有效的;如果您没有充分修复,您可能会遇到麻烦不过,首先要修复导致故障的损坏的数据结构。正如 Basile 提到的,弄乱保存的处理器状态也是有效的,以便返回“正常”不只是尝试运行相同的代码又是错误的指令;但这样做往往涉及手动解释机器指令和其他此类黑魔法。)

\n\n
\n

如果任何 SIGFPE、SIGILL、SIGSEGV 或 SIGBUS 信号在被阻塞时生成,则结果是未定义的,除非该信号是由另一个进程的操作或由 Kill()、pthread_kill() 函数之一生成的、raise() 或 sigqueue()。

\n
\n\n

(我不确定为什么这个措辞与其他两个有点不同;可能只是因为编写特定文档sigprocmask的人没有与编写信号操作的一般文档的人协调。)

\n\n
\n\n

0 Dima 将他们的问题标记为“Linux”,但为了未来读者的利益,我无论如何都会提出这个警告:我在这里写的所有内容都应该假定仅适用于符合 POSIX 的操作系统;首先,这意味着“您可能遇到的所有操作系统,Windows 除外”。例外很重要。Windows 对于线程和进程之间关系的概念与 POSIX 相当不同,并且具有完全不同(高级!)的报告 CPU 生成的错误程序异常的基本机制。Windows 上的信号是由 C 库模拟的,并且可能不会像我描述的那样运行。
\n大概实际上是 1pthread_kill。
\n 2请阅读整个系列的博客文章
\n 3具体来说,是 The Open Group 基本规范第 7 期 2013 版的在线副本,它也是“同时”的 IEEE 标准 1003.1、POSIX 2013 版。
\n 4不多,但聊胜于无;“信号操作”文档中有一个列表,但没有片段 ID 允许我直接指向它。

\n