构建我自己的 initrd 时如何填充 /dev 目录?

构建我自己的 initrd 时如何填充 /dev 目录?

我正在尝试学习有关 initrd 的知识。我已关注本教程从头开始构建我自己的 initrd,并在其上安装了 busybox。然后我用 isolinux 从它制作了一个 .iso,这样我就可以在 virtualbox 中测试它。效果很好!

我有来自 busybox 的基本命令,所以我想挂载一个文件系统。但 /dev 目录几乎是空的(没有 sda),除了我在遵循教程时创建的一些文件。我了解了udev,我认为这就是我所需要的。但是我不知道如何继续下去。

我应该从 udev 获取最新的源代码,编译它并将其添加到我的 initrd 中吗?然后在我的初始化脚本中调用 /bin/udev 或类似的东西?或者是否有其他/更好的方法来填充 /dev 目录?

编辑:关于我已经完成的工作的一些附加信息和更新。

  • 我在虚拟盒子中测试了所有内容。我刚刚在 Virtual Box 中安装了 ubuntu Minimal,从我的 initrd 中制作了一个 .iso,然后从 VirtualBox 中的 ISO 启动。
  • 我使用了 vmlinuz 以及/lib/modulesdebian-businesscard.iso 中的文件,并将它们复制到我的 initrd 中,该 initrd 是我按照之前链接的教程创建的。
  • 内核有CONFIG_DEVTMPFS=y
  • 一些设备出现在 中/dev,例如 tty0-tty63 和其他一些设备,但没有 sda/hda。
  • lspci -k在我当前运行的操作系统和虚拟框中运行以检查正在使用哪些模块。SATA Controller说它用作ahci模块。
  • 当我执行时,modprobe -v ahci它抱怨很多“未知符号:ata_some_stuff”,但之后它返回类似SCSI Subsystem initialized,ATA-6: VBOX HARDDISK和 的内容Direct-Access ATA VBOX HARDDISK。但是,仍然没有找到硬盘设备/dev

我当前的/init/脚本如下:

#!/bin/ash
mount -t devtmpfs none /dev
mount -t proc /proc /proc
mount -t sysfs none /sys
modprobe -v ahci
echo "Hello world"
exec /bin/ash --login

有谁知道我做错了什么以及我应该做什么?

答案1

虽然吉尔斯的答案是正确的,但它是老派:-)。另一件值得注意的事情(对术语的挑剔比任何事情都多)是您链接到的指南是有关如何创建 initramfs 的说明,而不是 initrd。两者很相似,用途相同,但图像的存储和加载方式有所不同。

无论如何,你的问题的答案实际上非常非常简单。

  1. devtmpfs在内核中启用( CONFIG_DEVTMPFS=y)
  2. mount -t devtmpfs none /dev作为脚本中的第一件事运行init

就是这样。 devtmpfs 将/dev像 udev 一样填充。您甚至不需要使用、或/dev等基础知识预先填充(在 initramfs 映像中)。nullzeroconsole

答案2

Udev/dev根据加载到内核中的驱动程序以及这些驱动程序检测到的设备自动填充。设备的名称及其权限基于管理员可以微调的一组规则。大多数Linux系统应该使用udev;例外情况是系统(通常是嵌入式),其硬件配置在系统设置时就已知,并且之后不会更改。

您通常会udev在启动序列的早期调用。在此之前您应该(必须?)做的几件事之一是 mount/proc/sys.启动守护进程后,调用udevadm trigger --action=add; udevadm settle使 udev 处理来自内核的所有待处理事件 ( trigger),并等待事件处理完毕后再继续 ( settle)。然后您可以继续查找包含根文件系统的设备。

除了二进制文件之外,您还需要initrd 上udevd的其他部分。udev这包括 中的配置文件/etc/udev、基本配置/lib/udev以及辅助二进制文件,scsi_id例如/lib/udev.您需要从包含在 initrd 中的 udev 规则调用的所有程序。

在 initrd 结束时,在将控制权转移到真正的根分区之前,您需要udevd像 initrd 中的所有其他程序一样停止。这不会从 中删除任何设备/dev。用于mount --move /dev /root/dev将安装移动/dev到真实根目录。

Gentoo 有一个initramfs 指南initramfs 维基页面其中提到了 udev 等。 Initramfs 是 initrd 的现代继承者,使用 cpio 存档而不是文件系统映像,并具有不同的进程接口(在 initrd 上,/linuxrc必须退出,而在 initramfs 上,/init必须exec从真实根进行 init);如今大多数系统都已切换(即使该文件可能仍称为 initrd)。

相关内容