![/init(或/linuxrc)脚本是否在/dev 中创建临时设备节点?](https://linux22.com/image/24216/%2Finit%EF%BC%88%E6%88%96%2Flinuxrc%EF%BC%89%E8%84%9A%E6%9C%AC%E6%98%AF%E5%90%A6%E5%9C%A8%2Fdev%20%E4%B8%AD%E5%88%9B%E5%BB%BA%E4%B8%B4%E6%97%B6%E8%AE%BE%E5%A4%87%E8%8A%82%E7%82%B9%EF%BC%9F.png)
考虑到 GRUB 执行以下几行:
kernel /vmlinuz root=/dev/sda1 ro
initrd /initrd
启动时,Linux 内核如何找到/dev/sda1
设备节点?
我知道 initrd/initramfs 映像包含存储(等)设备的模块,这些模块被加载到内存中以允许访问存储。让我烦恼的是root=/dev/sda1
内核如何准确地解析内核参数。
initrd/initramfs 中的/init
(或) 脚本是否创建目录,然后在其中创建设备节点?或者“主要”和“次要”数字是硬编码在内核中的?/linuxrc
/dev
/dev/sda1
/dev/sda1
答案1
如果您有 initramfs,内核只需解压并安装 initramfs,/init
然后执行。其他一切都将由/init
可执行文件处理。这也意味着内核不会安装root
引导参数中指定的设备。
不同的发行版使用不同的 initramfs 框架,例如德拉库特对于 Fedora 或initramfs 工具对于 Debian。最常见的解决方案是使用udev
,mdev
或 之类的东西devtmpfs
。有些也可能只是使用MAKEDEV
生成静态布局或将设备文件集成到其图像中。
如果您在没有 initramfs 的情况下启动,则内核只能从具有已知主/次编号的设备启动,例如,/dev/sda1
但不能从 lvm 设备启动。
答案2
根设备的主设备号和次设备号都存储在内核映像中(有关rdev
详细信息,请参阅 的联机帮助页)。
然而,内核命令行参数不被内核解释。初始 ramdisk initrd 包含一个带有最小 Linux 的文件系统,通常执行解释部分。 initrd 的工作方式取决于您的发行版。它可能只包含节点 /dev/sda1 或一些在运行时创建它的脚本/程序。
如果您使用的是基于 Debian 的 Linux,您可以像这样解压缩您的 ramdisk:
mkdir /tmp/initrd
cd /tmp/initrd
zcat /boot/path/to/initrd | cpio -iv
debian initrds 是脚本,您可以看看它是如何工作的。内核解压 initrd 后,它会启动init
您现在应该在 中找到的脚本/tmp/initrd
。请注意它所在的块for x in $(cat /proc/cmdline); do
。
其中/proc/cmdline
是使用 Grub 传递的参数(您现在可以使用 shell 检查/验证!)。如果您想更深入地了解 Debians initrd,您会注意到,您可以通过向root=/dev/nfs
Grub 传递选项来使您的内核/initrd 使用 NFS 共享作为根文件系统。当您这样做时,不会/dev/nfs
创建或安装任何节点。它只是告诉 initrd 做什么。
最后,每个这样的 initrd 都会运行某些选项提供的命令,例如init=
默认值/sbin/init
回到标题中的最初问题:是的 /init (最有可能)在运行时创建该节点。它使用各种程序/启发式/巫毒来找出如何挂载根文件系统。
答案3
初始代码运行一个名为的程序,mdev
它基本上是udev
.这将扫描所有设备并创建/dev
文件夹的初始内容。然后内核就能够有效地执行mount /dev/sda1 /
并开始查找整个系统。
看这里您想了解更多吗mdev
?
主设备号和次设备号实际上被硬编码到那些内核模块中,这些模块是设备驱动程序并且使用静态主设备号(例如,请参见文档/devices.txt在内核源代码中)。大多数(全部?)磁盘驱动程序内核模块都属于这一类。因此,正如 @Ulrich Dangel 所说,只要所需的模块静态链接到内核映像,某些内核就可以在没有 initramfs/initrd 的情况下启动。