理解操作系统开机引导和启动过程对于配置操作系统和解决相关启动问题是至关重要的。该文章陈述了GRUB2引导装载程序开机引导装载内核的过程和systemd初始化系统执行开机启动操作系统的过程。
事实上,操作系统的启动分为两个阶段:引导boot和启动startup。引导阶段开始于打开电源开关,结束于内核初始化完成和systemd进程成功运行。启动阶段接管了剩余*,直到操作系统进入可操作状态。
总体来说,Linux的开机引导和启动过程是相当容易理解,下文将分节对于不同步骤进行详细说明。
BIOS上电自检(POST)
引导装载程序(GRUB2)
注意,本文以GRUB2和systemd为载体讲述操作系统的开机引导和启动过程,是因为这二者是目前主流的linux发行版本所使用的引导装载程序和初始化软件。当然另外一些过去使用的相关软件仍然在一些Linux发行版本中使用。
BIOS上电自检(POST)
上电自检过程中其实Linux没有什么也没做,上电自检主要由硬件的部分来完成,这对于所有操作系统都一样。当电脑接通电源,电脑开始执行BIOS(基本输入输出系统BasicI/OSystem)的POST(上电自检PowerOnSelfTest)过程。
在1981年,IBM设计的*台个人电脑中,BIOS被设计为用来初始化硬件组件。POST作为BIOS的组成部分,用于检验电脑硬件基本功能是否正常。如果POST失败,那么这个电脑就不能使用,引导过程也将就此中断。
BIOS上电自检确认硬件的基本功能正常,然后产生一个BIOS中断INT13H,该中断指向某个接入的可引导设备的引导扇区。它所找到的*含有效的引导记录的*个引导扇区将被装载到内存中,并且控制权也将从引导扇区转移到此段代码。
引导扇区是引导加载器真正的*阶段。大多数Linux发行版本使用的引导加载器有三种:GRUB、GRUB2和LILO。GRUB2是最新的,也是相对于其他老的同类程序使用最广泛的。
GRUB被设计为兼容操作系统多重引导规范,它能够用来引导不同版本的Linux和其他的开源操作系统;它还能链式加载专有操作系统的引导记录。
GRUB允许用户从任何给定的Linux发行版本的几个不同内核中选择一个进行引导。这个特性使得操作系统,在因为关键软件不兼容或其它某些原因升级失败时,具备引导到先前版本的内核的能力。GRUB能够通过文件/boot/grub/grub.conf进行配置。(LCTT译注:此处指GRUB1)
GRUB1现在已经逐步被弃用,在大多数现代发行版上它已经被GRUB2所替换,GRUB2是在GRUB1的基础上重写完成。基于RedHat的发行版大约是在Fedora15和CentOS/RHEL7时升级到GRUB2的。GRUB2提供了与GRUB1同样的引导功能,但是GRUB2也是一个类似主框架(mainframe)系统上的基于命令行的前置操作系统(Pre-OS)环境,使得在预引导阶段配置更为方便和易操作。GRUB2通过/boot/grub2/grub.cfg进行配置。
两个GRUB的最主要作用都是将内核加载到内存并运行。两个版本的GRUB的基本*方式一致,其主要阶段也保持相同,都可分为3个阶段。在本文将以GRUB2为例进行讨论其*过程。GRUB或GRUB2的配置,以及GRUB2的命令使用均超过本文范围,不会在文中进行介绍。
虽然GRUB2并未在其三个引导阶段中正式使用这些阶段stage名词,但是为了讨论方便,我们在本文中使用它们。
阶段1
如上文POST(上电自检)阶段提到的,在POST阶段结束时,BIOS将查找在接入的磁盘中查找引导记录,其通常位于MBR(主引导记录MasterBootRecord),它加载它找到的*个引导记录中到内存中,并开始执行此代码。引导代码(及阶段1代码)必须非常小,因为它必须连同分区表放到硬盘的*个512字节的扇区中。在传统的常规MBR中,引导代码实际所占用的空间大小为446字节。这个阶段1的446字节的文件通常被叫做引导镜像(boot.img),其中不*含设备的分区信息,分区是一般单独添加到引导记录中。
由于引导记录必须非常的小,它不可能非常智能,且不能理解文件系统结构。因此阶段1的唯一功能就是定位并加载阶段1.5的代码。为了完成此任务,阶段1.5的代码必须位于引导记录与设备*个分区之间的位置。在加载阶段1.5代码进入内存后,控制权将由阶段1转移到阶段1.5。
阶段1.5
如上所述,阶段1.5的代码必须位于引导记录与设备*个分区之间的位置。该空间由于历史上的技术原因而空闲。*个分区的开始位置在扇区63和MBR(扇区0)之间遗留下62个512字节的扇区(共31744字节),该区域用于存储阶段1.5的代码镜像core.img文件。该文件大小为25389字节,故此区域有足够大小的空间用来存储core.img。
因为有更大的存储空间用于阶段1.5,且该空间足够容纳一些通用的文件系统驱动程序,如标准的EXT和其它的Linux文件系统,如FAT和NTFS等。GRUB2的core.img远比更老的GRUB1阶段1.5更复杂且更强大。这意味着GRUB2的阶段2能够放在标准的EXT文件系统内,但是不能放在逻辑卷内。故阶段2的文件可以存放于/boot文件系统中,一般在/boot/grub2目录下。
注意/boot目录必须放在一个GRUB所支持的文件系统(并不是所有的文件系统均可)。阶段1.5的功能是开始执行存放阶段2文件的/boot文件系统的驱动程序,并加载相关的驱动程序。
阶段2
GRUB阶段2所有的文件都已存放于/boot/grub2目录及其几个子目录之下。该阶段没有一个类似于阶段1与阶段1.5的镜像文件。相应地,该阶段主要需要从/boot/grub2/i386-pc目录下加载一些内核运行时模块。 GRUB阶段2的主要功能是定位和加载Linux内核到内存中,并转移控制权到内核。内核的相关文件位于/boot目录下,这些内核文件可以通过其文件名进行识别,其文件名均带有前缀vmlinuz。你可以列出/boot目录中的内容来查看操作系统中当前已经安装的内核。
GRUB2跟GRUB1类似,支持从Linux内核选择之一引导启动。RedHat*管理器(DNF)支持保留多个内核版本,以防最新版本内核发生问题而无法启动时,可以恢复老版本的内核。默认情况下,GRUB提供了一个已安装内核的预引导菜单,其中*括问题诊断菜单(recuse)以及恢复菜单(如果配置已经设置恢复镜像)。
阶段2加载选定的内核到内存中,并转移控制权到内核代码。
在选定的内核加载到内存中并开始执行后,在其进行任何*之前,内核文件首先必须从压缩格式解压自身。一旦内核自解压完成,则加载systemd进程(其是老式SystemV系统的init程序的替代品),并转移控制权到systemd。
这就是引导过程的结束。此刻,Linux内核和systemd处于运行状态,但是由于没有其他任何程序在执行,故其不能执行任何有关用户的功能性任务。
启动过程
启动过程紧随引导过程之后,启动过程使Linux系统进入可操作状态,并能够执行用户功能性任务。
首先,systemd挂载在/etc/fstab中配置的文件系统,*括内存交换文件或分区。据此,systemd必须能够访问位于/etc目录下的配置文件,*括它自己的。systemd借助其配置文件/etc/systemd/system/default.target决定Linux系统应该启动达到哪个状态(或目标态target)。default.target是一个真实的target文件的符号链接。对于桌面系统,其链接到graphical.target,该文件相当于旧式systemVinit方式的runlevel5。对于一个服务器操作系统来说,default.target更多是默认链接到multi-user.target,相当于systemV系统的runlevel3。emergency.target相当于单用户模式。
(LCTT译注:“target”是systemd新引入的概念,目前尚未发现有官方的准确译名,考虑到其作用和使用的上下文环境,我们认为翻译为“目标态”比较贴切。以及,“unit”是指systemd中服务和目标态等各个对象/文件,在此依照语境译作“单元”。)
注意,所有的目标态target和服务service均是systemd的单元unit。
如下表1是systemd启动的目标态target和老版systemVinit启动运行级别runlevel的对比。这个systemd目标态别名是为了systemd向前兼容systemV而提供。这个目标态别名允许系统管理员(*括我自己)用systemV命令(例如init3)改变运行级别。当然,该systemV命令是被转发到systemd进行解释和执行的。