Linux如何加载“ initrd”映像?


13

我一直在尝试了解引导过程,但是我头顶上只有一件事。

一旦启动Linux内核并安装了根文件系统(/),就可以运行程序并可以集成其他内核模块以提供其他功能。要挂载根文件系统,必须满足某些条件。内核需要相应的驱动程序来访问根文件系统所在的设备(特别是SCSI驱动程序)。内核还必须包含读取文件系统所需的代码(ext2,reiserfs,romfs等)。还可以想到,根文件系统已被加密。在这种情况下,需要密码来挂载文件系统。

初始ramdisk(也称为initdisk或initrd)精确地解决了上述问题。Linux内核提供了一个选项,即将小型文件系统加载到RAM磁盘,然后在安装实际的根文件系统之前在其中运行程序。initrd的加载由引导加载程序(GRUB,LILO等)处理。引导加载程序仅需要BIOS例程即可从引导介质加载数据。如果引导加载程序能够加载内核,则它也可以加载初始虚拟磁盘。不需要特殊的驱动程序。

如果/ boot不是一个不同的分区,而是/分区中的分区,那么引导加载程序是否不要求SCSI驱动程序访问“ initrd”映像和内核映像?如果您可以直接访问图像,那么为什么我们确实需要SCSI驱动程序?

Answers:


20

Nighpher,我将尝试回答您的问题,但是有关引导过程的更全面的描述,请尝试IBM文章

好的,我假设您使用GRUB或GRUB2作为引导加载程序进行解释。首先,当BIOS访问磁盘以加载引导加载程序时,它将利用其内置的磁盘访问例程存储在著名的13h中断中。引导加载程序(以及设置阶段的内核)在访问磁盘时会使用这些例程。请注意,BIOS在处理器的实模式(16位)模式下运行,因此它不能寻址超过2 ^ 20字节的RAM(2 ^ 20而不是2 ^ 16),因为实模式下的每个地址都由segment_address * 16 + offset组成,其中段地址和偏移量均为16位,请参见http://en.wikipedia.org/wiki/X86_memory_segmentation)。因此,这些例程不能访问超过1 MiB的RAM,这是一个严格的限制,并且带来了很大的不便。

BIOS直接从MBR加载引导加载程序代码-磁盘的前512个字节并执行它。如果使用的是GRUB,则该代码为GRUB阶段1。该代码将加载GRUB阶段1.5,该阶段位于磁盘空间的前32 KiB(称为DOS兼容性区域)中,或者位于文件系统的固定地址中。它不需要了解文件系统就可以做到这一点,甚至是在文件系统中处于阶段1.5时,它也是“原始”代码,可以直接加载到RAM中并执行:http : //www.pixelbeat.org/ docs / disk /。从磁盘到RAM的stage1.5负载使用BIOS磁盘访问例程。

在此处输入图片说明

Stage1.5包含文件系统实用程序,因此它可以从文件系统读取stage2(好吧,它仍然使用BIOS 13h从磁盘读取到RAM,但是现在它可以解密有关inode等的文件系统信息,并从文件中获取原始代码。磁盘)。由于磁盘寻址方式的限制,较早的BIOS可能无法访问整个HD-它们可能使用Cylinder-Head-Sector系统,无法寻址超过前8 GiB的磁盘空间:http://en.wikipedia。 org / wiki / Cylinder-head-sector

Stage2 将内核加载到RAM中(再次使用BIOS磁盘实用程序)。如果是2.6+内核,则还可以在其中编译initramfs,因此无需加载它。如果是较旧的内核,则引导加载程序还会将独立的initrd映像加载到内存中,以便内核可以挂载它并获取用于从磁盘挂载实际文件系统的驱动程序。

问题是内核(和ramdisk)的重量超过1 MiB,因此要将它们加载到RAM中,您必须先将内核加载到1 MiB,然后跳转到保护模式(32位),将加载的内核移至高内存(空闲)。前1个MiB(用于实模式),然后再次返回实(16位)模式,将虚拟磁盘从磁盘获取到前1个MiB(如果它是单独的initrd和更早的内核),可能再次切换到保护(32位)模式,将其放置在其所属位置,可能会返回到实模式(或不返回实模式):https : //stackoverflow.com/questions/4821911/does-grub-switch-to-protected-mode)并执行内核代码。警告:我不确定这部分说明的详尽性和准确性。

现在,当您最终运行内核时,您已经将它和ramdisk通过bootloader加载到RAM中,因此内核可以使用ramdisk中的磁盘实用程序来安装真正的根文件系统并将根旋转到它。ramfs驱动程序存在于内核中,因此它当然可以理解initramfs的内容。


Bootlader不能只是分块加载内核,而不是跳入保护模式吗?释放该1 MB的需求是什么。(对不起。。。)
rpthms 2013年

释放第一个1MiB的需要如下:引导加载程序只能在实模式下访问您的硬盘驱动器,因为它会使用实模式的BIOS实用程序(它们使用16位参数并使用16位操作)对其进行访问。实模式下只有前1个MiB看不到任何RAM。但是您需要将kernel + initramfs加载到RAM中,并且它们在RAM中占用约5 MiB的空间。这些BIOS实用程序将无法将5 MiB压缩到前1 MiB中。因此,引导加载程序必须将它们从磁盘复制到前1个MiB,然后进入保护模式并将它们从第一个1Mb RAM移至更高的RAM。现在更清楚了吗?:)
鲍里斯·伯科夫

1
整个阶段1 / 1.5 / 2都是grub遗留的东西。
psusi 2013年

1
@CMCDragonkai是的,stage2引导程序位于文件系统(即/boot分区)中。此时尚未加载内核-这是grub的stage1.5,后者通过其简约的文件系统驱动程序访问文件/boot系统(例如,/boot/grub文件中)的stage2 。内核也可以从/boot分区读取,但是稍后会在执行grub2代码和加载内核之后以及内核读取initramfs之后发生。您说的init.sh是initramfs吗?它驻留在/boot硬盘驱动器的分区中,然后grub的stage2将其放入RAM中,内核从RAM中读取它。
鲍里斯·伯科夫

1
Initrd 必须是一个单独的文件。较新的initramfs 可以链接到内核,但它并不必须是 -它也可以加载引导加载程序一个单独的文件。由于将initramfs文件定义为一系列cpio存档,因此某些引导程序(例如iPXE)甚至允许多个 initramfs文件,这些文件将一个接一个地加载到内存中。另外,尽管现在使用的实际技术是initramfs,但某些Linux发行版使用initrd样式的文件名来实现向后兼容性。
telcoM

1

我相信,可以归结为特定的引导程序支持的功能。例如。它不必知道组合的(引导+根)分区的特定文件系统。在这种情况下,您只需要创建一个单独的引导分区即可使其与您的引导加载程序一起使用,并且如何挂载根分区的任何其他复杂性都留在内核上,而从引导分区引导的initrd映像。Bootloader确实知道如何通过使用自身的驱动程序或利用BIOS例程来访问SCSI设备(以及其他设备,具体取决于所使用的Bootloader)。而且,它知道如何读取某些文件系统等。

考虑例如。UEFI引导方式,实际上UEFI固件已经知道如何访问EFI分区,读取它并从那里加载linux内核,而无需中间引导程序。在这种情况下,Linux映像与根分区分离,UEFI固件不必知道所有外部文件系统即可访问它。我相信将“启动”映像与“根”分区分开很有意义。如果没有其他用途,那么在设置根文件系统加密时就很有必要。


0

仅作记录,如果引导加载程序加载initrd,则值得测试另一个引导加载程序。我刚刚跑进像的情况时候LILO静静地忽略掉一个中等大小的正确指定的initrd(<4Mb的;在SATA SSD单ext4的根文件系统; GPT)和GRUB 2.00得手。

启动过程很快就结束了,

RAMDISK: Couldn't find valid RAM disk image starting at 0.
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(8,3)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.