你是否当初对操作系统为什么才能执行应用程序而倍感诧异?这么本文将为你揭露操作系统引导与启动的面纱。
理解操作系统开机引导和启动过程对于配置操作系统和解决相关启动问题是至关重要的。该文章陈述了GRUB2引导装载程序开机引导装载内核的过程和systemd初始化系统执行开机启动操作系统的过程。
事实上,操作系统的启动分为两个阶段:引导boot和启动startup。引导阶段开始于打开电源开关,结束于内核初始化完成和systemd进程成功运行。启动阶段接管了剩余工作,直至操作系统步入可操作状态。
总体来说,Linux的开机引导和启动过程是相当容易理解,下文将分节对于不同步骤进行详尽说明。
注意,本文以GRUB2和systemd为载体述说操作系统的开机引导和启动过程,是由于这两者是目前主流的linux发行版本所使用的引导装载程序和初始化软件。其实另外一些过去使用的相关软件依然在一些Linux发行版本中使用。
引导过程
引导过程能以两种方法之一初始化。其二,假若系统处于死机状态,这么打开电源按键将开启系统引导过程。其一,若果操作系统早已运行在一个本地用户(该用户可以是root或其他非特权用户),这么用户可以利用图形界面或命令行界面通过编程方法发起一个重启操作,因而触发系统引导过程。重启包括了一个死机和重新开始的操作。
BIOS上电自检(POST)
上电自检过程中虽然Linux没有哪些也没做,上电自检主要由硬件的部份来完成,这对于所有操作系统都一样。当笔记本接通电源,笔记本开始执行BIOS(基本输入输出系统BasicI/OSystem)的POST(上电自检PowerOnSelfTest)过程。
在1981年,IBM设计的第一台个人笔记本中,BIOS被设计为拿来初始化硬件组件。POST作为BIOS的组成部份,用于检验笔记本硬件基本功能是否正常。假如POST失败,这么这个笔记本就不能使用,引导过程也凑合此中断。
BIOS上电自检确认硬件的基本功能正常,之后形成一个BIOS中断INT13H,该中断指向某个接入的可引导设备的引导磁道。它所找到的包含有效的引导记录的第一个引导磁道将被装载到显存中,而且控制权也将从引导磁道转移到此段代码。
引导磁道是引导加载器真正的第一阶段。大多数Linux发行版本使用的引导加载器有三种:GRUB、GRUB2和LILO。GRUB2是最新的,也是相对于其他老的同类程序使用最广泛的。
GRUB2
GRUB2全称是GRandUnifiedBootLoader,Version2(第二版大一统引导装载程序)。它是目前流行的大部份Linux发行版本的主要引导加载程序。GRUB2是一个用于计算机找寻操作系统内核并加载其到显存的智能程序。因为GRUB这个词组比GRUB2更便于书写和阅读,在下文中,除特殊指明以外,GRUB将代指GRUB2。
GRUB被设计为兼容操作系统多重引导规范,它就能拿来引导不同版本的Linux和其他的开源操作系统;它能够链式加载专有操作系统的引导记录。
GRUB容许用户从任何给定的Linux发行版本的几个不同内核中选择一个进行引导。这个特点致使操作系统,在由于关键软件不兼容或其它个别缘由升级失败时,具备引导到以前版本的内核的能力。GRUB才能通过文件/boot/grub/grub.conf进行配置。(LCTT评注:此处指GRUB1)
GRUB1如今早已逐渐被弃用,在大多数现代发行版上它早已被GRUB2所替换,GRUB2是在GRUB1的基础上重写完成。基于RedHat的发行版大概是在Fedora15和CentOS/RHEL7时升级到GRUB2的。GRUB2提供了与GRUB1同样的引导功能linux 发邮件,而且GRUB2也是一个类似主框架(mainframe)系统上的基于命令行的后置操作系统(Pre-OS)环境,致使在预引导阶段配置更为便捷和易操作。GRUB2通过/boot/grub2/grub.cfg进行配置。
两个GRUB的最主要作用都是将内核加载到显存并运行。两个版本的GRUB的基本工作方法一致,其主要阶段也保持相同,都可分为3个阶段。在本文将以GRUB2为例进行讨论其工作过程。GRUB或GRUB2的配置,以及GRUB2的命令使用均超过本文范围,不会在文中进行介绍。
尽管GRUB2并未在其四个引导阶段中即将使用这种阶段stage名词,并且为了讨论便捷,我们在本文中使用它们。
阶段1
如上文POST(上电自检)阶段提及的,在POST阶段结束时,BIOS将查找在接入的c盘中查找引导记录,其一般坐落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加载选取的内核到显存中,并转移控制权到内核代码。
内核
内核文件都是以一种自解压的压缩格式储存以节约空间,它与一个初始化的显存映像和储存设备映射表都储存于/boot目录之下。
在选取的内核加载到显存中并开始执行后,在其进行任何工作之前,内核文件首先必须从压缩格式解压自身。一旦内核自解压完成,则加载systemd进程(其是旧式SystemV系统的程序的代替品),并转移控制权到systemd。
这就是引导过程的结束。此刻,Linux内核和systemd处于运行状态,而且因为没有其他任何程序在执行,故其不能执行任何有关用户的功能性任务。
启动过程
启动过程紧跟引导过程以后,启动过程使Linux系统步入可操作状态,并才能执行用户功能性任务。
systemd
systemd是所有进程的父进程。它负责将Linux主机带到一个用户可操作状态(可以执行功能任务)。systemd的一些功能远较老式init程序更丰富,可以管理运行中的Linux主机的许多方面LINUX虚机,包括挂载文件系统,以及开启和管理Linux主机的系统服务等。并且systemd的任何与系统启动过程无关的功能均不在此文的讨论范围。
首先,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新引入的概念,目前仍未发觉有官方的确切译名,考虑到其作用和使用的上下文环境中国linux系统有哪些?,我们觉得翻译为“目标态”比较贴切。以及,“unit”是指systemd中服务和目标态等各个对象/文件,在此根据语境译作“单元”。)
注意,所有的目标态target和服务service均是systemd的单元unit。
如下表1是systemd启动的目标态target和老版systemVinit启动运行级别runlevel的对比。这个systemd目标态别称是为了systemd往前兼容systemV而提供。这个目标态别称容许系统管理员(包括我自己)用systemV命令(比如init3)改变运行级别。其实,该systemV命令是被转发到systemd进行解释和执行的。
SystemV运行级别systemd目标态systemd目标态别称描述
halt.target
停止系统运行但不切断电源。
poweroff.target
runlevel0.target
停止系统运行并切断电源.
emergency.target
单用户模式,没有服务进程运行,文件系统也没挂载。这是一个最基本的运行级别,仅在主控制台上提供一个shell用于用户与系统进行交互。
rescue.target
runlevel1.target
挂载了文件系统,仅运行了最基本的服务进程的基本系统,并在主控制台启动了一个shell访问入口用于确诊。
runlevel2.target
多用户,没有挂载NFS文件系统,并且所有的非图形界面的服务进程早已运行。
multi-user.target
runlevel3.target
所有服务都已运行,但只支持命令行插口访问。
runlevel4.target
未使用。
graphical.target
runlevel5.target
多用户,且支持图形界面插口。
reboot.target
runlevel6.target
重启。
default.target
这个目标态target是总是multi-user.target或graphical.target的一个符号链接的别称。systemd总是通过default.target启动系统。default.target绝不应当指向halt.target、poweroff.target或reboot.target。
表1老版本systemV的运行级别与systemd与目标态target或目标态别称的比较
每位目标态target有一个在其配置文件中描述的依赖集中国linux系统有哪些?,systemd须要首先启动其所需依赖,这种依赖服务是Linux主机运行在特定的功能级别所要求的服务。当配置文件中所有的依赖服务都加载并运行后,即说明系统运行于该目标级别。
systemd也会查看旧式的systemVinit目录中是否存在相关启动文件,若存在,则systemd按照这种配置文件的内容启动对应的服务。在Fedora系统中,过时的网路服务就是通过该方法启动的一个实例。
如右图1是直接从bootup的man页面拷贝而至。它展示了在systemd启动过程中通常的风波序列和确保成功的启动的基本的次序要求。
sysinit.target和basic.target目标态可以被视作启动过程中的状态检测点。虽然systemd的设计本意是并行启动系统服务,并且部份服务或功能目标态是其它服务或目标态的启动的前提。系统将暂停于检测点直至其所要求的服务和目标态都满足为止。
sysinit.target状态的抵达是以其所依赖的所有资源模块都正常启动为前提的,所有其它的单元,如文件系统挂载、交换文件设置、设备管理器的启动、随机数生成器种子设置、低级别系统服务初始化、加揭秘服务启动(假如一个或则多个文件系统加密的话)等都必须完成,并且在sysinit.target中这种服务与模块是可以并行启动的。
sysinit.target启动所有的低级别服务和系统初具功能所需的单元,这种都是步入下一阶段basic.target的必要前提。
图1:systemd的启动流程
在sysinit.target的条件满足之后,systemd接出来启动basic.target,启动其所要求的所有单元。basic.target通过启动下一目标态所需的单元而提供了更多的功能,这包括各类可执行文件的目录路径、通信sockets,以及定时器等。
最后,用户级目标态(multi-user.target或graphical.target)可以初始化了,应当注意的是multi-user.target必须在满足图形化目标态graphical.target的依赖项之前先达成。
图1中,以*开头的目标态是通用的启动状态。当抵达其中的某一目标态,则说明系统早已启动完成了。假如multi-user.target是默认的目标态,则成功启动的系统将以命令行登陆界面呈现于用户。假如graphical.target是默认的目标态,则成功启动的系统将以图形登入界面呈现于用户,界面的具体款式将按照系统所配置的显示管理器而定。
故障讨论
近来我须要改变一台使用GRUB2的Linux笔记本的默认引导内核。我发觉一些GRUB2的命令在我的系统上不能用,也可能是我使用方式不正确。至今,我一直不晓得是何缘由造成,此问题须要进一步探究。
grub2-set-default命令没能在配置文件/etc/default/grub中成功地设置默认内核索引,以至于期望的取代内核并没有被引导启动。故在该配置文件中我自动修改GRUB_DEFAULT=saved为GRUB_DEFAULT=2,2是我须要引导的安装好的内核文件的索引。之后我执行命令grub2-mkconfig>/boot/grub2/grub.cfg创建了新的GRUB配置文件,该方式如预期的规避了问题,并成功引导了取代的内核。
推论
GRUB2、systemd初始化系统是大多数现代Linux发行版引导和启动的关键组件。虽然在实际中,systemd的使用还存在一些争议,然而GRUB2与systemd可以密切地配合先加载内核,之后启动一个业务系统所须要的系统服务。
虽然GRUB2和systemd都比其前任要愈发复杂,而且它们愈发容易学习和管理。在man页面有大量关于systemd的帮助说明,也在线收录了完整的此帮助说明。下边有更多相关信息链接。
附加资源
作者简介:
DavidBoth居住在加拿大北卡罗纳州的首府罗利,是一个Linux开源贡献者。他早已从事IT行业40余年,在IBM院士OS/220余年。1981年,他在IBM开发了第一个关于最初的IBM个人笔记本的培训课程。他也曾在RedHat院士RHCE课程,也曾供职于MCIworldcom,Cico以及北卡罗纳州等。他早已为Linux开源社区工作近20年。
via:
作者:DavidBoth译者:penghuster校对:wxy
本文由LCTT原创编译,Linux中国荣誉推出
文章评论