4

在通过 安装的信号处理程序void (*sa_sigaction)(int, siginfo_t *, void *);中,我如何判断 SIGILL 是源自非法指令还是源自已发送 SIGILL 的某个进程?我查看si_pid了siginfo_t,但是如果遇到非法指令,这似乎是未初始化的,因此我无法根据它做出决定。- 当然,我正在寻找一个最好是简单和便携的解决方案,而不是阅读指令代码si_addr并试图确定它是否合法。

4

1 回答 1

8

真正的SIGILL将具有si_codeILL_ 值之一(例如,ILL_ILLADR)。用户请求的 SIGILL 将具有si_codeSI_ 值之一(通常为 SI_USER)。

相关的POSIX 值是:

[Kernel-generated]
ILL_ILLOPC  Illegal opcode.
ILL_ILLOPN  Illegal operand.
ILL_ILLADR  Illegal addressing mode.
ILL_ILLTRP  Illegal trap.
ILL_PRVOPC  Privileged opcode.
ILL_PRVREG  Privileged register.
ILL_COPROC  Coprocessor error.
ILL_BADSTK  Internal stack error.

[User-requested]
SI_USER     Signal sent by kill().
SI_QUEUE    Signal sent by the sigqueue().
SI_TIMER    Signal generated by expiration of a timer set by timer_settime().
SI_ASYNCIO  Signal generated by completion of an asynchronous I/O request.
SI_MESGQ    Signal generated by arrival of a message on an empty message queue.

例如,这个问题中的配方给了我 ILL_ILLOPN,而kill(1)kill(2)我零(SI_USER)。

当然,您的实现可能会将值添加到 POSIX 列表中。从历史上看,用户或流程生成的si_code值 <= 0,这仍然很常见。您的实现也可能有一个方便的宏来提供帮助。例如,Linux 提供:

#define SI_FROMUSER(siptr)      ((siptr)->si_code <= 0)
#define SI_FROMKERNEL(siptr)    ((siptr)->si_code > 0)
于 2013-06-28T15:22:49.713 回答