-5 linux-kernel
我使用 YouTube 教程(https://www.youtube.com/watch?v=asnXWOUKhTA)创建了一个最小的 Linux 发行版,但如果我执行 ctrl + c ,内核就会崩溃!
编辑:当我执行 ctrl + d 时,我很困惑
这正是链接教程中从 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
Run Code Online (Sandbox Code Playgroud)
在本教程中,添加的一行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!
Run Code Online (Sandbox Code Playgroud)
(在这种情况下,与其说它init被杀死,不如说它实际上自己退出了。PID #1 通常不应该在不关闭系统或为自身提供有效后继者的情况下退出。)
还有其他迹象表明,这个“最小的 Linux 发行版”是一个非常基本的玩具设置。启动时/bin/sh,它说:
/bin/sh: can't access tty; job control turned off
Run Code Online (Sandbox Code Playgroud)
这表明/bin/sh未在正确设置的控制台会话中运行,并且无法以通常的方式对Ctrl+C或Ctrl+击键做出反应。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()自身的新版本来启用更新getty如果发现控制台或配置的 TTY 没有任何实时进程,则为它们启动一个进程)wait(-1)获取来自孤立进程的 SIGCHLD 信号,为此内核将分配 PID #1 作为其 PPID。每当这样的孤立进程死亡时,wait()就会读取其结果代码,一旦完成,内核将能够从其进程表中清除死亡进程,因此它不会像僵尸一样徘徊。这可以通过将BusyBox/bin/init的合适配置添加到 initrd 文件中并将最后一行替换为/init:
exec /bin/init
Run Code Online (Sandbox Code Playgroud)
这里exec很重要:它会导致当前以 PID #1 身份运行脚本的 shell 将/init其自身替换为,在新的二进制文件之前省略系统/bin/init调用。因此,PID 编号不会改变,并且将能够承担其真正 PID #1 的角色。fork()exec()/bin/init