内核如何挂载根分区?


29

我的问题是关于从单独的/ boot分区引导Linux系统。如果大多数配置文件位于单独的/分区中,内核如何在引导时正确地将其安装?

在这方面的任何阐述都是很棒的。我感觉好像缺少一些基本知识。我最关心的是操作的过程和顺序。

谢谢!

编辑:我想我需要问的是更多的root内核参数中使用的dev文件。例如,假设我将我的根参数设置为root = / dev / sda2。内核如何映射/ dev / sda2文件?


尽管下面的人员介绍了initrd,但很少讨论为何使用initrd。我的印象是因为像Debian这样的发行版希望在同一体系结构的许多不同机器上使用一个内核,但是可能在硬件上有很大不同。通过内核模块对硬件支持进行模块化,使之成为可能。initrd不需要太多的硬件支持即可启动,并且一旦启动,它将加载必要的硬件模块以继续进行。对此的详细说明/纠正是赞赏的。
Faheem Mitha

您必须先挂载/才能挂载/ boot,因为没有/ boot的目录就没有/ boot。
psusi 2011年

Answers:


20

Linux最初使用ramdisk(称为initrd“ INITial RamDisk” 称为ramdisk)引导/。该磁盘仅具有足够的容量,可以查找实际的根分区(包括所需的任何驱动程序和文件系统模块)。它将根分区挂载到上的临时挂载点initrd,然后调用pivot_root(8)以交换根挂载点和临时挂载点,将initrd位置保留在umounted上,并将实际的根文件系统放在上/


2
如果没有像LFS(linuxfromscratch.org)这样的initrd怎么办?
Shickadance先生,2011年

@先生。Shickadance:没有研究过LFS的工作方式,我想他们会确保内核已将所有必需的模块编译进去(或通过GRUB 2加载),这种可能性是新的,以至于很多发行版都没有注意到它)可以在实际的根分区上启动。
geekosaur 2011年

4
@先生。Shickadance。没有initrd的不仅仅是LFS。任何编译自己内核的人都可以选择不使用initrd,这是我在Gentoo上所做的。
jonescb 2011年

1
@Faheem:grub2模块与内核模块不同。我看到grub2可以加载内核模块,但是我不知道的一件事是它是否适用于Linux内核或仅适用于* BSD(引导加载程序加载内核模块是正常的)。我怀疑需要教会内核在哪里可以找到已加载模块的地址映射,并且每个人都需要转移到grub2(在某些发行版中grub1仍然是标准的)。
geekosaur 2011年

1
initrd已被initramfs取代,因为pivot_root被视为肮脏的hack。
psusi 2011年

41

在远古时代,内核被硬编码为知道根fs的设备主/次编号,并在初始化所有内置在内核中的设备驱动程序之后挂载该设备。该rdev实用程序可用于修改内核映像中的根设备编号,而不必重新编译它。

最终,引导加载程序出现了,并且可以将命令行传递给内核。如果root=传递了参数,则会告诉内核根fs而不是内置值在哪里。需要访问的驱动程序仍然必须内置在内核中。尽管该参数看起来像/dev目录中的普通设备节点,但显然/dev在挂载根fs之前没有目录,因此内核无法在其中查找dev节点。而是将某些众所周知的设备名称硬编码到内核中,以便可以将字符串转换为设备编号。因此,内核可以识别诸如之类的东西/dev/sda1,而不能识别诸如/dev/mapper/vg0-rootUUID或卷UUID之类的奇特事物。

后来,initrd进入了图片。引导程序会与内核一起加载initrd映像,该映像是某种压缩的文件系统映像(gext ext2映像,romfs压缩映像,squashfs最终成为主导)。内核会将该映像解压缩到ramdisk中,并将ramdisk挂载为根fs。该映像包含一些其他驱动程序和引导脚本,而不是real init。这些引导脚本执行了各种任务,以识别硬件,激活RAID阵列和LVM之类的东西,检测UUID并解析内核命令行以找到真实的根目录,这些根目录现在可以由UUID,卷标和其他高级东西指定。然后将真正的根fs挂载到/initrd,然后执行pivot_root系统调用以进行内核交换//initrd,然后/sbin/init在实际根目录上执行,然后将其卸载/initrd并释放虚拟磁盘。

最后,今天我们有了initramfs。这类似于initrd,但它是压缩的cpio归档文件,而不是作为加载到ramdisk中的压缩文件系统映像。将tmpfs挂载为根,然后将归档文件提取到那里。引导脚本不是使用pivot_root被认为是肮脏的hack,而是initramfs将真实的根目录装入其中/root,删除tmpfs根目录中的所有文件,然后删除chroot/root和exec /sbin/init


1
chroot之后,是否会自动卸载tmpfs?它会消失吗?
jiggunjer

@jiggunjer,不,它仍然存在,只是空的(除了包含/ root目录),并且不再使用。
psusi

我对您提到的root fs的每次迭代都学到了一些新知识。好答案!
jpaugh

3

听起来您正在询问内核如何“知道”哪个分区是根分区,而又无法访问/ etc上的配置文件。

内核可以像其他程序一样接受命令行参数。GRUB或大多数其他引导加载程序可以接受命令行参数作为用户输入,或存储它们并通过菜单提供各种命令行参数组合。引导加载程序在加载时将命令行参数传递给内核(我不知道该约定的名称或机制,但可能类似于应用程序从运行中的内核中从调用进程接收命令行参数的方式)。

这些命令行选项之一是root,您可以在其中指定根文件系统,即root=/dev/sda1

如果内核使用initrd,则引导加载程序负责告诉内核它在哪里,或者将initrd放在标准内存位置(我认为),至少这是它在我的Guruplug上的工作方式。

完全可能不指定一个,然后在开始抱怨找不到根文件系统后立即让内核崩溃。

可能还有其他方法可以将此选项传递给内核。


3
当没有initrd / initramfs时,这是正确的解释,但它缺少一个难题。通常,内核会识别设备,例如/dev/sda1因为它是文件系统中的条目。您可以做cp -p /dev/sda1 /tmp/foo并且/tmp/foo将代表同一台设备。在内核命令行上,内核使用内置的解析器,该解析器遵循通常的设备命名约定:sda1表示第一个类似SCSI的磁盘的第一个分区。
吉尔(Gilles)“所以,别再邪恶了”,

@Gilles,所以现代内核仍然无法处理基于UUID的卷装载?没有initrdinitramfs我的意思。它必须是/dev/sdx形式上的“简单”分区吗?
jiggunjer

1
@jiggunjer现代内核确实支持通过UUID搜索卷。请参阅init/do_mounts.c
吉尔斯(Gilles)'“ SO-别再邪恶了”

1

Grub挂载/boot分区,然后执行内核。在Grub的配置中,它告诉内核将什么用作根设备。

例如在Grub的menu.lst

kernel /boot/linux root=/dev/sda2

1

来吧,GRUB不会“挂载” / boot,它只会读取“ menu.lst”和某些模块,它也不是LINUX内核的一部分。调用内核时,您将通过根分区传递“ root”参数。最糟糕的是,内核知道/ boot已经挂载(LOL)。

下一步:geekosaur是正确的,Linux使用压缩映像格式的初始ramdisk,然后通过调用挂载实际的根文件系统pivot_root。因此,Linux从映像开始运行,然后从本地磁盘驱动器运行。


1
Grub绝对有能力“挂载”文件系统,尤其是在grub2中。当然,它能够/ doing /的全部功能就是寻找一个或另一个带区的可启动内核,但这仍在继续。另外,除非内核将对硬盘至关重要的驱动程序编译为模块,否则linux 不需要 initrd。
Shadur 2011年

5
ibm.com/developerworks/linux/library/l-linuxboot这是Linux内核在引导时所做的相当简洁的摘要。
jsbillings 2011年

2
@Shadur,来自mount联机帮助页:在Unix系统中可访问的所有文件都排列在一棵大树中,该文件树根于/。这些文件可以分布在多个设备上。mount命令用于将在某些设备上找到的文件系统附加到大文件树。 -由于GRUB使用的文件系统未附加到文件层次结构,因此未安装
D4RIO 2011年

1
@Shadur,顺便说一句:显然initrd并不是必需的,因为它只是另一个根文件系统,但是它通常用作较小的启动时根,因为内核加载了启动所需的内容,然后进行了引导,最后还加载了其他所有内容。
D4RIO 2011年

1
@ d4rio它们是由GRUB而不是linux挂载的-当您将grub视为其自身的微内核操作系统而不是引导加载程序时,将更容易理解。
2011年

1

引导加载程序(无论是grub还是lilo或其他)都会告诉内核在哪里查看root=标志,并有选择地initrd在引导内核之前将初始ramdisk加载到内存中。

然后,内核加载,测试其硬件和设备驱动程序,并在系统中四处查看(您可以通过键入来查看该诊断信息dmesg;如今,它可能滚动得太快而无法查看),然后尝试挂载该文档中提到的分区。的root=参数。

如果存在initrd,则首先安装它,并在安装根文件系统之前先加载并探测其中的所有模块/设备驱动程序。这样,您可以将硬盘驱动器的驱动程序编译为模块,并且仍然可以启动。

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.