本文介绍了是SIGSEGV特殊的,当`kill`生成?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我知道当内核使用它报告内存访问冲突时,不能忽略 SIGSEGV 。但是如果我为 SIGSEGV 安装一个不起作用的信号处理程序,然后另一个进程使用 kill 发送给我这个信号,这将会像我使用正常信号一样Grijesh Chauhan的答案在技术上是正确的,但很难做到。 code>理解,所以我要写出我自己的博览会基本上相同的点。有脚注。 Dima询问当一个线程安装 SIGSEGV ,然后另一个线程使用 kill 在该线程上生成 SIGSEGV 。一句话的答案是处理程序运行,什么也不做,然后控制返回到中断线程内的正常流程。与内核生成 SIGSEGV 作为对实际内存访问冲突的响应不同,此方案不会触发未定义的行为 。但是, SIGSEGV 及其朋友( SIGBUS , SIGFPE 和 SIGILL )是为内核告诉你的程序它做了一些如此令人发指的事情,必须是一个错误,正常执行不能继续,你想清理一点之前你死了吗?因此,将它们用于其他任何东西是不明智的。有几个信号( SIGUSR1 , SIGUSR2 和 SIGRTMIN 通过 SIGRTMAX )保留为每个应用程序使用,但它喜欢; 对于更长的答案,我将从POSIX标准中选择 3 子部分信号操作。首先,四个信号 SIGFPE , SIGILL , SIGSEGV 和 SIGBUS 像任何其他信号一样,可以异步地传递 - 在没有特定的时间 - 因为某段代码使用系统调用(例如 kill )来生成它们。当发生这种情况时,它们被处理为与任何其他信号完全相同,其默认动作恰恰是终止程序异常;请注意,许多其他信号具有此属性,包括为应用程序使用保留的属性。如果您的程序只需要担心接收 SIGFPE , SIGILL , SIGSEGV 和 SIGBUS 当它们由 kill 和朋友生成时,它可以做所有的正常事与它们:阻塞它们,忽略它们,建立信号处理程序,对任何对异步信号处理程序有效的信号处理程序,通过 sigwait signalfd ,而不是正常的异步系统陷阱类似的交付机制。 但是。 SIGFPE , SIGILL , SIGSEGV 和 SIGBUS 也由内核响应于触发硬件异常的不同类型的错误程序行为(例如尝试访问未映射存储器)同步地生成。同步意味着信号在执行违规CPU指令时立即发送,并且在该同一线程上,而不是在该进程中恰好使其解除阻塞的任何线程。我们真的不是开玩笑的立即部分:如果有一个信号处理程序,当它执行时,保存的程序计数器将指向导致任何类型的硬件异常的确切指令。内核不能允许执行通过导致CPU发出硬件异常的指令来执行,因此POSIX说这是关于尝试丢弃这些信号,而不是终止进程或采取一些剧烈的恢复操作: 进程的行为在忽略 SIGFPE , SIGILL , SIGSEGV 或 SIGBUS 信号(), sigqueue()或 raise()。 (在上下文中忽略之后意味着如果内核尝试在动作设置为 SIG_IGN 。) 进程的行为在从信号捕获函数正常返回后未定义对于不是由kill(),sigqueue()或raise()生成的SIGBUS,SIGFPE,SIGILL或SIGSEGV信号。 (通常返回表示不通过调用(sig)longjmp 。 是有效的,至少就内核而言,解开堆栈并在其他地方恢复执行;你可能会遇到麻烦,如果你没有充分地修复损坏的数据结构,导致故障在第一位。它也是有效的,如Basile所提到的,混乱保存的处理器状态,以便返回正常不只是试图再次运行相同的坏指令;但 往往涉及手动解释机器指令和其他这种黑魔法。) SIGFPE,SIGILL,SIGSEGV或SIGBUS信号在它们被阻塞时被产生,结果是未定义的,除非该信号是由另一个进程的动作或由函数kill(),pthread_kill(),raise() ,或sigqueue()。 (我不知道为什么这个措辞与其他两个有点不同,为 sigprocmask 撰写特定文档的人员$ c> 未与撰写的人协调信号动作的一般文件。) Dima标记了他们的问题 Linux,但是为了未来读者的利益,我将提出这个警告:我在这里写的一切都应该假定仅适用于符合POSIX的操作系统; 到第一顺序,这意味着你可能会遇到的所有操作系统,除了Windows。例外是重要的。 Windows与POSIX有不同的线程和进程之间关系的概念,以及一个完全不同的(优越的)报告CPU生成的错误程序异常的基本机制。 Windows上的信号由C库仿真,并且可能不会按照我的描述行为。 实际上可能是 pthread_kill 。 2 的在线副本请仔细阅读此全部系列博文 //pubs.opengroup.org/onlinepubs/9699919799/rel =nofollow>开放组基本规范第7期2013年版,它也同时是IEEE标准1003.1,POSIX的2013版。 不是很多,但不是什么;文档中的信号操作文档中有一个列表,但没有片段ID,让我指出你正确的。 I know that SIGSEGV can't be ignored when the kernel uses it to report a memory access violation. But if I install a signal handler for SIGSEGV that does nothing, and then another process uses kill to send me that signal, will this behave the same as if I had used a "normal" signal (like SIGUSR1) instead? 解决方案 Grijesh Chauhan's answer is technically correct but difficult to understand, so I am going to write out my own exposition of basically the same points. With footnotes.Dima asks what happens when one thread installs a do-nothing handler for SIGSEGV and then another thread uses kill to generate SIGSEGV on that thread. The one-sentence answer is that the handler runs, does nothing, and then control returns to normal flow within the interrupted thread. Unlike when the kernel generates SIGSEGV as a response to an actual memory access violation, this scenario does not trigger undefined behavior. However, the intended purpose of SIGSEGV and its friends (SIGBUS, SIGFPE, and SIGILL) is for the kernel to tell your program that it has done something so heinous that there must be a bug, normal execution cannot continue, would you like to clean up a little before you get killed? It is therefore unwise to use them for anything else. There are several signals (SIGUSR1, SIGUSR2, and SIGRTMIN through SIGRTMAX) reserved for each application to use however it likes; you should use one of those instead.For the longer answer, I am going to crib from the POSIX standard, subsection Signal Actions. First, the four signals SIGFPE, SIGILL, SIGSEGV, and SIGBUS, like any other signal, can be delivered "asynchronously"—at no particular time—because some piece of code used a system call (such as kill) to generate them. When this happens, they are treated exactly the same as any other signal whose default "action" happens to be "terminate the program abnormally"; note that many other signals have this property, including those reserved for application use. If your program only ever has to worry about receiving SIGFPE, SIGILL, SIGSEGV, and SIGBUS when they are generated by kill and friends, it can do all of the normal things with them: block them, ignore them, establish signal handlers that do anything that is valid for an asynchronous signal handler, receive them via sigwait or signalfd rather than the normal asynchronous system trap-like delivery mechanism.However. SIGFPE, SIGILL, SIGSEGV, and SIGBUS are also generated "synchronously" by the kernel in response to different kinds of erroneous program behavior that trigger hardware exceptions, such as attempting to access unmapped memory. Synchronously means that the signal is delivered immediately upon execution of the offending CPU instruction, and on that same thread rather than any thread in the process that happens to have it unblocked. And we're really not kidding about the "immediately" part: if there's a signal handler, when it executes, the saved program counter will be pointing at the exact instruction that caused whatever sort of hardware exceptions it was. The kernel can't allow execution to proceed through an instruction that causes the CPU to issue a hardware exception, so POSIX says this about attempting to discard these signals rather than terminate the process or take some drastic recovery action: The behavior of a process is undefined after it ignores a SIGFPE, SIGILL, SIGSEGV, or SIGBUS signal that was not generated by kill(), sigqueue(), or raise().("After it ignores" in context means "if the kernel tries to generate one of these signals synchronously when the action is set to SIG_IGN.) The behavior of a process is undefined after it returns normally from a signal-catching function for a SIGBUS, SIGFPE, SIGILL, or SIGSEGV signal that was not generated by kill(), sigqueue(), or raise().("Returns normally" means "not by calling (sig)longjmp". It is valid, at least as far as the kernel is concerned, to unwind the stack and resume execution somewhere else; you may be in for trouble if you haven't sufficiently fixed up the damaged data structure that caused the fault in the first place, though. It's also valid, as Basile mentioned, to mess with the saved processor state so that returning "normally" doesn't just try to run the same bad instruction again; but doing that tends to involve manually interpreting machine instructions and other such black magic.) If any of the SIGFPE, SIGILL, SIGSEGV, or SIGBUS signals are generated while they are blocked, the result is undefined, unless the signal was generated by the action of another process, or by one of the functions kill(), pthread_kill(), raise(), or sigqueue().(I'm not sure why this wording is a little different from the other two; probably just because the person who wrote the specific documentation for sigprocmask didn't coordinate with the person who wrote the general documentation for signal actions.) Dima tagged their question "Linux", but I am going to put in this caveat anyway, for the benefit of future readers: Everything I write here should be assumed to apply only to POSIX-conformant operating systems; to first order, that means "all OSes you are likely to encounter, except Windows." The exception is important. Windows has a rather different notion of the relationship between threads and processes than POSIX does, and a completely different (superior!) fundamental mechanism for reporting CPU-generated erroneous-program exceptions. Signals on Windows are emulated by the C library and probably do not behave as I describe. presumably actually pthread_kill. please read this entire series of blog posts specifically, the online copy of The Open Group Base Specifications Issue 7, 2013 edition, which is also "simultaneously" the 2013 edition of IEEE Standard 1003.1, POSIX. not a lot, but more than nothing; there's a list in the "Signal Actions" document, but no fragment ID allowing me to point you right at it. 这篇关于是SIGSEGV特殊的,当`kill`生成?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 08-22 16:57