如果你用过 Linux,可能没想过系统启动时藏着一个有趣的难题——就像"先有鸡还是先有蛋":内核需要加载模块才能挂载根分区,但这些模块又存放在根分区里。这看似矛盾的问题,其实靠一个叫 initrd 的工具解决了。今天就用大白话聊聊这个 Linux 启动的关键角色。
什么是 Linux 启动的"鸡与蛋问题"?
先看一个场景:当你按下电源,Linux 系统开始启动时,内核(相当于系统的"大脑")首先被加载。但内核要完成启动,必须先找到并挂载根分区(也就是存放系统文件的地方,类似电脑的 C 盘)。
问题来了:
- 挂载根分区可能需要特殊模块(比如支持 ext4 文件系统、LVM 分区或 RAID 阵列的驱动);
- 这些模块却存放在根分区的
/lib/modules/
目录下; - 内核没挂载根分区,就拿不到这些模块;可拿不到模块,又挂载不了根分区……
这不就陷入了"要挂载根分区必须有模块,要有模块必须先挂载根分区"的循环吗?这就是 Linux 启动时的"鸡与蛋问题"。
救星登场:initrd 是什么?
为了解决这个死循环,Linux 引入了 initrd(Initial RAM Disk,初始内存磁盘)。简单说,它是一个临时的"迷你系统",被提前加载到内存中,帮内核完成"挂载根分区"这个关键步骤。
initrd 的作用:
- 提前加载必要模块:initrd 里打包了挂载根分区必需的驱动(比如 LVM、RAID 模块),这些模块不需要依赖根分区,因为 initrd 直接在内存中运行。
- 帮内核挂载根分区:用这些提前加载的模块,initrd 可以顺利找到并挂载根分区。
- 交接控制权:根分区挂载完成后,initrd 就功成身退,把系统控制权交还给内核,让内核继续加载根分区里的完整系统。
initrd 是怎么工作的?
整个过程像一场接力赛:
- 电脑启动后,GRUB(启动引导程序)先加载内核和 initrd 到内存;
- 内核启动后,先运行 initrd 里的程序,加载挂载根分区需要的模块;
- initrd 成功挂载根分区后,告诉内核:"根分区准备好了,你接着干吧!";
- 内核接管后,从根分区加载剩余的系统文件,完成启动。
没有 initrd,内核就会卡在"找不到根分区驱动"的阶段,系统启动失败。
什么时候需要重新生成 initrd?
initrd 是系统安装时自动生成的,通常不用手动管。但以下情况需要重新生成它:
- 手动升级了内核;
- 安装了新的硬件驱动(比如 RAID 卡、特殊硬盘的驱动);
- 根分区的文件系统或分区方式改变(比如从普通分区换成 LVM)。
如何重新生成 initrd?
用 mkinitrd
命令就能生成新的 initrd 文件,以 CentOS/RHEL 系统为例:
基本命令:
sudo mkinitrd -f /boot/initrd-$(uname -r).img $(uname -r)
$(uname -r)
会自动获取当前内核版本(比如5.14.0-1.el7.x86_64
),不用手动输入;-f
表示强制覆盖已有的 initrd 文件;- 生成的文件会保存在
/boot
目录下,命名格式是initrd-内核版本.img
。
强制添加特定模块:
如果需要手动加入某个模块(比如 SCSI 硬盘驱动 scsi_mod
),用 --with
参数:
sudo mkinitrd --with=scsi_mod -f /boot/initrd-$(uname -r).img $(uname -r)
总结:initrd 是启动的"关键跳板"
简单说,initrd 就是 Linux 启动时的"临时工具箱"——提前把挂载根分区需要的工具(模块)打包好,帮内核打破"鸡与蛋"的循环。
记住两个关键点:
- 没有 initrd,内核可能找不到根分区,系统启动失败;
- 升级内核或修改硬件驱动后,记得用
mkinitrd
重新生成 initrd,避免启动问题。