如何确保 control + c 不会杀死内核?

如何确保 control + c 不会杀死内核?

我使用了 YouTube 教程(https://www.youtube.com/watch?v=asnXWOUKhTA)创建一个最小的 Linux 发行版,但如果我执行 ctrl + c 内核崩溃!

编辑:当我执行 ctrl + d 时,我很困惑

答案1

这正是链接教程中从 44:00 点开始发生的情况:

教程从44:00开始

本教程使用最小的 shell 脚本/init

#!/bin/sh
mount -t sysfs sysfs /sys
mount -t proc proc /proc
mount -t devtmpfs udev /dev
sysctl -w kernel.printk="2 4 1 7"
/bin/sh

在本教程中,添加的一行poweroff -f作为最后一行/init被添加到创建 initrd 文件的脚本中,但 initrd 实际上并未更新以包含该命令。

由于 PID #1 将是执行脚本的 shell,而/bin/sh显示 root 提示符的将是其子进程,因此 PID #1 shell 将等待/bin/sh退出,一旦退出,PID #1 也将退出。之后就不再有任何进程了;正如其他人在评论中指出的那样,PID #1 的丢失将使内核非常不高兴。这将导致内核恐慌,并显示以下消息:

Kernel panic - not syncing: Attempted to kill init!

(在这种情况下,与其说它init被杀死,不如说它实际上自己退出了。PID #1 通常不应该在不关闭系统或为自身提供有效后继者的情况下退出。)

还有其他迹象表明,这个“最小的 Linux 发行版”是一个非常基本的玩具设置。启动时/bin/sh,它说:

/bin/sh: can't access tty; job control turned off

这表明/bin/sh未在正确设置的控制台会话中运行,并且无法以通常的方式对Ctrl+CCtrl+击键做出反应。Z相反,在收到 Ctrl-C 时,将/bin/sh像常规 shell 命令一样退出 - 之后,脚本/init已到达文件末尾,因此运行脚本的 shell(作为 PID #1)也将退出。

Ctrl-D 可能最终具有相同的效果,因为它是标准的 Unix 文件结束击键:通常 TTY 驱动程序检测 Ctrl-D 并将其转换为文件结束条件,但由于 shell 这里说can't access tty,它可能会自行检测 Ctrl-D。基本上,shell 会将标准输入上的文件结束条件解释为“用户以某种方式断开连接”,因此 shell 将退出...导致 PID #1 脚本到达其末尾。

为了进一步开发这个“最小的 Linux 发行版”,第一步是将脚本/init替换为满足 PID #1 工作要求的进程:

  • 理想情况下永远不会退出,但也许能够使用exec()自身的新版本来启用更新
  • 正确初始化控制台会话和任何其他配置的 TTY(可能通过监视始终存在与这些进程关联的进程,getty如果发现控制台或配置的 TTY 没有任何实时进程,则为它们启动一个进程)
  • 收获孤立僵尸:PID #1 应该花费大部分时间来wait(-1)获取来自孤立进程的 SIGCHLD 信号,为此内核将分配 PID #1 作为其 PPID。每当这样的孤立进程死亡时,就会wait()读取其结果代码,一旦完成,内核将能够从其进程表中清除死亡进程,因此它不会像僵尸一样徘徊。

这可以通过添加合适的配置来实现忙碌盒/bin/init到 initrd 文件,并将最后一行替换/init为:

exec /bin/init

这里exec很重要:它会导致当前以 PID #1 身份运行脚本的 shell/init将自身替换为/bin/init,方法是在ing 新二进制文件fork()之前省略系统调用。exec()因此,PID 编号不会改变,并且将/bin/init能够承担其真正 PID #1 的角色。

相关内容