1. Linux 启动过程
当系统首次引导时,或系统被重置时,处理器会执行一个位于已知位置处的代码。在个人计算机(PC)中,这个位置在基本输入/输出系统(BIOS)中,它保存在主板上的闪存中。嵌入式系统中的中央处理单元(CPU)会调用这个重置向量来启动一个位于闪存/ROM 中的已知地址处的程序。在这两种情况下,结果都是相同的。因为 PC 提供了很多灵活性,BIOS 必须确定要使用哪个设备来引导系统。稍后我们将详细介绍这个过程。
当找到一个引导设备之后,第一阶段的引导加载程序就被装入 RAM 并执行。这个引导加载程序在大小上小于 512 字节(一个扇区),其作用是加载第二阶段的引导加载程序。
当第二阶段的引导加载程序被装入 RAM 并执行时,通常会显示一个动画屏幕,并将 Linux 和一个可选的初始 RAM 磁盘(临时根文件系统)加载到内存中。在加载映像时,第二阶段的引导加载程序就会将控制权交给内核映像,然后内核就可以进行解压和初始化了。在这个阶段中,第二阶段的引导加载程序会检测系统硬件、枚举系统链接的硬件设备、挂载根设备,然后加载必要的内核模块。完成这些操作之后启动第一个用户空间程序(init),并执行高级系统初始化工作。
Linux启动过程(ZZ)
2.什么是initrd
initrd 的英文含义是 boot loader initialized RAM disk,就是由 boot loader 初始化的内存盘,是在系统引导过程中挂载的一个临时根文件系统,用来支持两阶段的引导过程。initrd 映像中包含了支持 Linux 内核两阶段启动过程所需要的必要可执行程序和系统文件。
内核引导过程中,初始 RAM 磁盘(initrd)是由阶段 2 引导加载程序加载到内存中的,它会被复制到 RAM 中并挂载到系统上。这个 initrd 会作为 RAM 中的临时根文件系统使用,并允许内核在没有挂载任何物理磁盘的情况下完整地实现引导。由于与外围设备进行交互所需要的模块可能是 initrd 的一部分,因此内核可以非常小,但是仍然需要支持大量可能的硬件配置。在内核引导之后,就可以正式装备根文件系统了(通过 pivot_root):此时会将 initrd 根文件系统卸载掉,并挂载真正的根文件系统
initrd.img主要是用于在内核启动时加载内核模块,这需要理解启动系统的过程。举个简单的例子:你的根文件系统是ext3,当你编译内核时将ext3文件系统以外挂模块的方式编译到内核。在启动Linux系统时,首先会加载内核,然后是加载init进程。当加载init进程时,需要读取ext3文件系统(根文件系统),而此时由于ext3文件系统的支持是以外挂模块的方式加载的,也必须到根文件系统读取。问题就来了:此时如何使内核加载ext3文件系统的内核模块呢?此我们就可以将ext3的模块文件放入initrd.img中,由boot loader将该镜像载入内存中。这就是initrd.img的主要作用。
如果想使用initrd.img,可以将在能够读取文件系统之前需要使用到的所用功能都编译到内核当中即可。
3.两阶段启动的优点
第一阶段启动的目的是为第二阶段的启动扫清一切障碍,最主要的是加载根文件系统存储介质的驱动模块。我们知道根文件系统可以存储在包括IDE、SCSI、USB在内的多种介质上,如果将这些设备的驱动都编译进内核,可以想象内核会非常的庞大和臃肿。
当内核被引导并进行初始化之后,内核就可以启动自己的第一个用户空间应用程序了。这是第一个调用的使用标准 C 库编译的程序。在此之前,还没有执行任何标准的 C 应用程序。在桌面 Linux 系统上,第一个启动的程序通常是 /sbin/init。
PS:前段时间第一次给本科生讲课,今天在做一个作业时又用到了些相似的知识,于是把当时的PPT大致整理了下,在做PPT时参考了大量网络上的资料,现在已经无法确定具体的出处。如果文章中有理解错误之处,欢迎斧正。