Update 20170220 An introduction to the Linux boot and startup processes.md

This commit is contained in:
penghuster 2017-08-19 01:31:29 +08:00 committed by GitHub
parent d10383a7df
commit 95cf23c43e

View File

@ -1,4 +1,4 @@
#Linux开机引导和启动过程简介 # Linux开机引导和启动过程简介
--- ---
>你是否曾经对操作系统为何能够执行应用程序而感到疑惑?那么本文将为你揭开操作系统引导与启动的面纱。 >你是否曾经对操作系统为何能够执行应用程序而感到疑惑?那么本文将为你揭开操作系统引导与启动的面纱。
@ -23,11 +23,11 @@
注意,本文以 GRUB2 和 systemd 为载体讲述操作系统的开机引导和启动过程,是因为两者是目前主流的 linux 发行版本所使用的引导加载内核和初始化系统的软件。当然另外一些过去使用的相关软件仍然在一些 Linux 发行版本中使用。 注意,本文以 GRUB2 和 systemd 为载体讲述操作系统的开机引导和启动过程,是因为两者是目前主流的 linux 发行版本所使用的引导加载内核和初始化系统的软件。当然另外一些过去使用的相关软件仍然在一些 Linux 发行版本中使用。
##引导过程 ## 引导过程
发起引导过程的方法有两种。首先,如果系统处于关机状态,那么打开电源按钮将开启系统引导过程。其次,如果操作系统已经运行在一个本地用户(该用户可是 root 或其他非特权用户),那么用户可以借助图形界面或命令行界面通过编程方式发起一个重启操作,从而触发系统引导过程。重启包括了一个关机和启动操作。 发起引导过程的方法有两种。首先,如果系统处于关机状态,那么打开电源按钮将开启系统引导过程。其次,如果操作系统已经运行在一个本地用户(该用户可是 root 或其他非特权用户),那么用户可以借助图形界面或命令行界面通过编程方式发起一个重启操作,从而触发系统引导过程。重启包括了一个关机和启动操作。
###BIOS上电自检 ### BIOS上电自检
上电自检过程中其实 Linux 没有什么也没做,上电自检主要由硬件完成,这对于所有操作系统都一样。当电脑接通电源,电脑开始执行 BIOS基本输入输出系统的 POST上电自检过程。 上电自检过程中其实 Linux 没有什么也没做,上电自检主要由硬件完成,这对于所有操作系统都一样。当电脑接通电源,电脑开始执行 BIOS基本输入输出系统的 POST上电自检过程。
@ -37,7 +37,7 @@ BIOS 上电自检确认硬件的基本功能正常,然后产生一个 BIOS 中
设备启动记录中代码加载是引导加载器真正的第一阶段。大多数 Linux 发行版本使用的引导加载器一共有 3 种GRUBGRUB2 和 LILO。GRUB2 是最新出现的,也是相对于其他老的选项使用最广泛的。 设备启动记录中代码加载是引导加载器真正的第一阶段。大多数 Linux 发行版本使用的引导加载器一共有 3 种GRUBGRUB2 和 LILO。GRUB2 是最新出现的,也是相对于其他老的选项使用最广泛的。
###GRUB2 ### GRUB2
GRUB2 全称是 Grand Unified BootLoaderVersion 2。它是目前流行的大部分 Linux 发行版本的通用启动加载器。GRUB2 是一个用于寻找操作系统内核并加载其到内存的智能程序。由于 GRUB 比 GRUB2 易于书写和阅读在下文中除特殊指明以外GRUB 将代指 GRUB2。 GRUB2 全称是 Grand Unified BootLoaderVersion 2。它是目前流行的大部分 Linux 发行版本的通用启动加载器。GRUB2 是一个用于寻找操作系统内核并加载其到内存的智能程序。由于 GRUB 比 GRUB2 易于书写和阅读在下文中除特殊指明以外GRUB 将代指 GRUB2。
@ -49,13 +49,13 @@ GRUB1 现在已经逐步被弃用,它已经被更新的版本 GRUB2 所替换
两个 GRUB 的最主要作用都是完成内核加载并启动内核。两个版本的 GRUB 的基本工作方式一致其主要阶段也保持相同都可分为3个阶段。在本文将以 GRUB2 为例进行讨论其工作过程。GRUB 或 GRUB2 的配置,以及 GRUB2 的使用命令均超过本文范围,不会在文中进行介绍。 两个 GRUB 的最主要作用都是完成内核加载并启动内核。两个版本的 GRUB 的基本工作方式一致其主要阶段也保持相同都可分为3个阶段。在本文将以 GRUB2 为例进行讨论其工作过程。GRUB 或 GRUB2 的配置,以及 GRUB2 的使用命令均超过本文范围,不会在文中进行介绍。
####阶段 1 #### 阶段 1
如上文 POST上电自检阶段提到在 POST 阶段结束时BIOS 将查找在启动设备中查找引导记录,其通常位于 MBR主引导记录它加载该引导记录中代码进入内存并开始执行此代码。引导代码必须存储于引导记录由于一个记录的大小为 512 字节且引导记录还必须存储该所在设备的分区信息,导致了引导代码必须非常小。 在实际中,引导代码在住引导扇区中占用的空间大小为 446 字节,该 446 字节的文件通常被叫做引导镜像boot.img其中不包含设备的分区信息分区是一般单独添加到引导记录中。 如上文 POST上电自检阶段提到在 POST 阶段结束时BIOS 将查找在启动设备中查找引导记录,其通常位于 MBR主引导记录它加载该引导记录中代码进入内存并开始执行此代码。引导代码必须存储于引导记录由于一个记录的大小为 512 字节且引导记录还必须存储该所在设备的分区信息,导致了引导代码必须非常小。 在实际中,引导代码在住引导扇区中占用的空间大小为 446 字节,该 446 字节的文件通常被叫做引导镜像boot.img其中不包含设备的分区信息分区是一般单独添加到引导记录中。
由于引导记录的大小限制,它不可能非常智能,且不能理解文件系统结构。因此阶段 1 的唯一功能就是加载阶段 1.5 的所需的代码。为了完成此任务,阶段 1.5 的代码必须位于引导记录与设备第一个分区之间的位置。在加载阶段 1.5 代码进入内存后,控制权将有阶段 1 转移到阶段 1.5。 由于引导记录的大小限制,它不可能非常智能,且不能理解文件系统结构。因此阶段 1 的唯一功能就是加载阶段 1.5 的所需的代码。为了完成此任务,阶段 1.5 的代码必须位于引导记录与设备第一个分区之间的位置。在加载阶段 1.5 代码进入内存后,控制权将有阶段 1 转移到阶段 1.5。
####阶段 1.5 #### 阶段 1.5
如上所述,阶段 1.5 的代码必须位于引导记录与设备第一个分区之间的位置。该空间由于历史技术原因而空闲。第一个分区的开始位置在扇区 63 和 MBR记录 0之间遗留下 62 个 512 字节的记录(共 31744 字节),该区域用于存储阶段 2 的代码镜像 core.img 文件。该文件大小为 25389 字节,故此区域有足够大小的空间用来存储 core.img。 如上所述,阶段 1.5 的代码必须位于引导记录与设备第一个分区之间的位置。该空间由于历史技术原因而空闲。第一个分区的开始位置在扇区 63 和 MBR记录 0之间遗留下 62 个 512 字节的记录(共 31744 字节),该区域用于存储阶段 2 的代码镜像 core.img 文件。该文件大小为 25389 字节,故此区域有足够大小的空间用来存储 core.img。
@ -63,7 +63,7 @@ GRUB1 现在已经逐步被弃用,它已经被更新的版本 GRUB2 所替换
注意 /boot 目录必须是一个 GRUB 所支持的文件系统(并不是所有的文件系统均可)。阶段 1.5 的功能是启动阶段 2 所需要的文件系统,并将阶段 2 需要的文件存储到 /boot 根目录下,且加载相关的驱动程序。 注意 /boot 目录必须是一个 GRUB 所支持的文件系统(并不是所有的文件系统均可)。阶段 1.5 的功能是启动阶段 2 所需要的文件系统,并将阶段 2 需要的文件存储到 /boot 根目录下,且加载相关的驱动程序。
####阶段 2 #### 阶段 2
GRUB 阶段 2 所有的文件都已存放于 /boot/grub2 目录及其几个子目录之下。该阶段没有一个类似于阶段 1 与阶段 1.5 的镜像文件。相应地,该阶段主要需要从 /boot/grub2/i386-pc 目录下加载一些内核运行时模块。 GRUB 阶段 2 所有的文件都已存放于 /boot/grub2 目录及其几个子目录之下。该阶段没有一个类似于阶段 1 与阶段 1.5 的镜像文件。相应地,该阶段主要需要从 /boot/grub2/i386-pc 目录下加载一些内核运行时模块。
@ -73,7 +73,7 @@ GRUB2 根 GRUB1 类似支持选择从某个内核文件引导启动。Red Hat
阶段 2 加载选择的内核到内存中,并转移控制权到内核代码。 阶段 2 加载选择的内核到内存中,并转移控制权到内核代码。
###内核 ### 内核
内核文件都是以一种自解压的压缩格式存储,它与一个初始化的内存映像和存储设备映射表都存储于 /boot 目录之下。 内核文件都是以一种自解压的压缩格式存储,它与一个初始化的内存映像和存储设备映射表都存储于 /boot 目录之下。
@ -81,11 +81,11 @@ GRUB2 根 GRUB1 类似支持选择从某个内核文件引导启动。Red Hat
在引导过程的结束时Linux 内核和 systemd 处于运行状态,但是由于没有其他任何程序在执行,故其不能执行任何有关用户的功能性任务。 在引导过程的结束时Linux 内核和 systemd 处于运行状态,但是由于没有其他任何程序在执行,故其不能执行任何有关用户的功能性任务。
##启动过程 ## 启动过程
启动过程紧随引导过程之后,启动过程使 Linux 系统进入可操作状态,并能够执行用户功能性任务。具体来说,就是系统启动相关的系统守护进程。 启动过程紧随引导过程之后,启动过程使 Linux 系统进入可操作状态,并能够执行用户功能性任务。具体来说,就是系统启动相关的系统守护进程。
###systemd ### systemd
systemd 是所有进程的父进程。它负责拉起宿主操作系统到一个用户可操作状态可以执行功能任务。systemd 相对于 init 进程扩展了一些管理该宿主进程各个方面的新功能,包括文件系统挂载,以及开启和管理系统服务等具体业务功能,但是 systemd 的任何与系统启动过程无关的功能均不在此文的讨论范围。 systemd 是所有进程的父进程。它负责拉起宿主操作系统到一个用户可操作状态可以执行功能任务。systemd 相对于 init 进程扩展了一些管理该宿主进程各个方面的新功能,包括文件系统挂载,以及开启和管理系统服务等具体业务功能,但是 systemd 的任何与系统启动过程无关的功能均不在此文的讨论范围。
@ -95,18 +95,18 @@ systemd 是所有进程的父进程。它负责拉起宿主操作系统到一个
如下表 1 是 systemd 启动的 targets 和老版 systemV init 启动状态点对比。这个 **systemd target aliases** systemd 状态别名)是为了 systemd 向前兼容 systemV 而提供。这个 target 别名允许系统管理员(包括我自己)用 systemV 命令(例如 init 3改变运行级别。当然该 systemV 命令也可以转发到 systemd 进行解释和执行。 如下表 1 是 systemd 启动的 targets 和老版 systemV init 启动状态点对比。这个 **systemd target aliases** systemd 状态别名)是为了 systemd 向前兼容 systemV 而提供。这个 target 别名允许系统管理员(包括我自己)用 systemV 命令(例如 init 3改变运行级别。当然该 systemV 命令也可以转发到 systemd 进行解释和执行。
|SystemV 运行级别 | systemd target | systemd target 别名 | 描述 | |SystemV 运行级别 | systemd target | systemd target 别名 | 描述 |
|:---:|---|---|---| |:---:|---|---|---|
| | halt.target | | 在不下电的情况下停止系统. | | | halt.target | | 在不下电的情况下停止系统. |
| 0 | poweroff.target | runlevel0.target | 停止系统运行并切断电源. | | 0 | poweroff.target | runlevel0.target | 停止系统运行并切断电源. |
| S | emergency.target | | 单用户模式,没有服务进程运行,文件系统也没挂载。这是用于紧急救援模式的一个基本的运行状态,仅仅能够通过在本地运行 shell 与系统进行交互。| | S | emergency.target | | 单用户模式,没有服务进程运行,文件系统也没挂载。这是用于紧急救援模式的一个基本的运行状态,仅仅能够通过在本地运行 shell 与系统进行交互。|
| 1 | rescue.target | runlevel1.target | 该状态是一个挂在了文件系统,仅运行了部分基本服务进程的基本系统,并在主控制台启动了一个 shell 访问入口用于诊断。 | | 1 | rescue.target | runlevel1.target | 该状态是一个挂在了文件系统,仅运行了部分基本服务进程的基本系统,并在主控制台启动了一个 shell 访问入口用于诊断。 |
| 2 | | runlevel2.target | 多用户,没有挂在 NFS 文件系统,但是所有的非图形界面服务进程已经运行。 | | 2 | | runlevel2.target | 多用户,没有挂在 NFS 文件系统,但是所有的非图形界面服务进程已经运行。 |
| 3 | multi-user.target | runlevel3.target | 所有服务都已运行,只支持命令接口访问. | | 3 | multi-user.target | runlevel3.target | 所有服务都已运行,只支持命令接口访问. |
| 4 | | runlevel4.target | 暂未使用. | | 4 | | runlevel4.target | 暂未使用. |
| 5 | graphical.target | runlevel5.target | 多用户,且支持图形界面接口. | | 5 | graphical.target | runlevel5.target | 多用户,且支持图形界面接口. |
| 6 | reboot.target | runlevel6.target | 重启 | | 6 | reboot.target | runlevel6.target | 重启 |
| | default.target | | 这个状态是对于多用户或图形界面状态的一个代指。systemd 总是通过 default.target 启动系统。default.target 绝不应该代指 halt.target, poweroff.target 或 reboot.target。 | | | default.target | | 这个状态是对于多用户或图形界面状态的一个代指。systemd 总是通过 default.target 启动系统。default.target 绝不应该代指 halt.target, poweroff.target 或 reboot.target。 |
*表 1 systemd 与老版本 systemV的启动状态点比较* *表 1 systemd 与老版本 systemV的启动状态点比较*
@ -175,19 +175,19 @@ systemd 也会查看 systemV init 遗留的目录中是否存在相关启动文
图 1 中,以*开头的状态target是通用的启动状态。当到达其中的某一状态则说明系统已经成功启动。如果 **multi-user.target** 是默认的目标状态,则成功启动的系统将以命令行登录界面呈现于用户。如果 **graphical.target** 是默认的目标状态,则成功启动的系统将以图形登陆界面呈现于用户,界面的具体样式将根据系统所配置的显示管理器而定。 图 1 中,以*开头的状态target是通用的启动状态。当到达其中的某一状态则说明系统已经成功启动。如果 **multi-user.target** 是默认的目标状态,则成功启动的系统将以命令行登录界面呈现于用户。如果 **graphical.target** 是默认的目标状态,则成功启动的系统将以图形登陆界面呈现于用户,界面的具体样式将根据系统所配置的显示管理器而定。
##问题讨论 ## 问题讨论
最近我需要将将一台 Linux 电脑的内核引导方式从旧版 GRUB1 更改为 GRUB2。我发现一些 GRUB2 的命令在我的系统上不能用,也可能是我使用方法不正确。至今,我仍然不知道是何原因导致,此问题需要进一步探究。 最近我需要将将一台 Linux 电脑的内核引导方式从旧版 GRUB1 更改为 GRUB2。我发现一些 GRUB2 的命令在我的系统上不能用,也可能是我使用方法不正确。至今,我仍然不知道是何原因导致,此问题需要进一步探究。
**grub2-set-default** 命令没能在配置文件 **/etc/default/grub** 中成功设置内核引导索引,以至于期望的内核并没有被引导启动。故在该配置文件中我手动更改 **GRUB_DEFAULT=saved****GRUB_DEFAULT=2**2 是我需要引导安装的内核文件所在设备的索引。然后我执行命令 **grub2-mkconfig > /boot/grub2/grub.cfg** 创建了新的 GRUB 配置文件,该方法成功规避了命令行无效的问题,并成功更改了系统引导方式。 **grub2-set-default** 命令没能在配置文件 **/etc/default/grub** 中成功设置内核引导索引,以至于期望的内核并没有被引导启动。故在该配置文件中我手动更改 **GRUB_DEFAULT=saved****GRUB_DEFAULT=2**2 是我需要引导安装的内核文件所在设备的索引。然后我执行命令 **grub2-mkconfig > /boot/grub2/grub.cfg** 创建了新的 GRUB 配置文件,该方法成功规避了命令行无效的问题,并成功更改了系统引导方式。
##结论 ## 结论
GRUB2, systemd 和 init 都是发行版 Linux 引导和启动的关键组件。尽管在实际中, systemd 的使用还存在一些争议,但是 GRUB2 与 systemd 结合的方式能够方便地引导内核并成功启动系统。 GRUB2, systemd 和 init 都是发行版 Linux 引导和启动的关键组件。尽管在实际中, systemd 的使用还存在一些争议,但是 GRUB2 与 systemd 结合的方式能够方便地引导内核并成功启动系统。
尽管 GRUB2 和 systemd 都比其前任要更加复杂,但是它们更加容易学习和管理。在 man 页面有大量关于 systemd 的帮助说明freedesktop.org 也在线收录了完整的此帮助说明。下面有更多相关信息链接。 尽管 GRUB2 和 systemd 都比其前任要更加复杂,但是它们更加容易学习和管理。在 man 页面有大量关于 systemd 的帮助说明freedesktop.org 也在线收录了完整的此帮助说明。下面有更多相关信息链接。
##附加资源 ## 附加资源
- [GNU GRUB](https://en.wikipedia.org/wiki/GNU_GRUB) (Wikipedia) - [GNU GRUB](https://en.wikipedia.org/wiki/GNU_GRUB) (Wikipedia)
- [GNU GRUB Manual](https://www.gnu.org/software/grub/manual/grub.html) (GNU.org) - [GNU GRUB Manual](https://www.gnu.org/software/grub/manual/grub.html) (GNU.org)