谁能解释一下IOT指令(核心转储)指的是什么?

R-R*_*ock 11 c linux segmentation-fault

I\xe2\x80\x99m 在执行 C 程序时遇到以下问题:

\n
~$ ./a.out\nzsh IOT instruction (core dumped) ./a.out\n
Run Code Online (Sandbox Code Playgroud)\n

我\xe2\x80\x99以前从未见过这个,而且我不\xe2\x80\x99不知道如何解决它。它是什么?

\n

请注意,我\xe2\x80\x99m 不是在寻找解决此问题的方法,而是了解问题所在,以便我可以修复它。谷歌没有提供任何有帮助的结果。

\n

Nat*_*dge 32

tl;dr: 这意味着abort()被调用了。现在,你必须弄清楚它为什么被称为。(核心转储可能会有所帮助。)

但是,为什么会出现奇怪的消息?我决定调查一下。

从前,有一台名为PDP-11 的计算机。它有一条名为“I/O Trap”的指令IOT,该指令会导致操作系统陷入某种类型的陷阱。PDP/11 上的 Unix 似乎会通过向进程传递特定信号来处理此陷阱,该信号的数值被分配给SIGIOT中的宏<signal.h>

现代 Linux 仍然支持该宏,因此硬编码信号宏列表的旧程序仍然可以编译。然而,它被分配给与更常见的相同的数字(6)SIGABRTabort() ,这是调用时发出的信号。所以实际上,SIGIOT它只是 的遗留别名SIGABRT

但消息呢?我们正在努力做到这一点。请记住,宏名称SIGIOTSIGABRT仅在编译时存在;在运行时,进程看到的只是整数值 6。要将其转换为人类可读的值,通常的方法是调用标准库strsignal函数。在使用 glibc 的 Linux 上,返回相当合理的strsignal(6)字符串。Aborted这是大多数 shell 用来报告杀死进程的信号的方法。

但 zsh 出于某种原因想要有所不同。他们不使用标准strsignal功能,而是推出自己的功能。他们有一对脚本 ( ),可以解析系统文件以查看存在哪些信号,然后生成一个查找表以将数值映射到预定义的字符串。awk 代码如下所示:signame1.awk signame2.awksignal.h

    if (signam == "ABRT")   { msg[signum] = "abort" }
    if (signam == "ALRM")   { msg[signum] = "alarm" }
    # ...
    if (signam == "IO")     { msg[signum] = "i/o ready" }
    if (signam == "IOT")    { msg[signum] = "IOT instruction" }
    if (signam == "KILL")   { msg[signum] = "killed" }
    # ...
Run Code Online (Sandbox Code Playgroud)

现在你看到了这个问题。由于SIGABRT定义为 6,因此当脚本处理#define SIGABRT 6来自 的行时<signal.h>,它将设置msg[6] = "abort"。那就太好了。但SIGIOT也定义为 6,因此当它开始处理该行时,它将设置,替换之前msg[6] = "IOT instruction"的字符串。

结果,使用 zsh 时,常见的SIGABRT信号会被报告为奇怪的IOT instruction消息。这可以说是 zsh 中的一个小错误。它被报告为 Debian bug,但上游似乎没有报告。

一个更严重的副作用是kill -ABRT在 zsh 下不起作用;要发送中止信号,您必须改为发送中止信号kill -IOT,这可能没有人知道该怎么做。

我刚刚向 zsh-workers 邮件列表发送了一条关于它的消息。