仅供个人参考
概述
Linux 的开机引导和启动过程:
- BIOS(Basic Input / Output System) 上电自检(POST)
- 引导装载程序 (GRUB2)
- 内核初始化
- 启动 systemd,其是所有进程之父。
BIOS上电自检(POST)
BIOS:基本输入输出系统(Basic I/O System)
POST:上电自检(Power On Self Test)
POST 作为 BIOS 的组成部分,用于检验电脑硬件基本功能是否正常。如果 POST 失败,那么这个电脑就不能使用,引导过程也将就此中断。POST过程中其实 Linux 没有什么也没做,POST主要由硬件的部分来完成,这对于所有操作系统都一样。
BIOS 上电自检确认硬件的基本功能正常,然后产生一个 BIOS 中断 INT 13H,该中断指向某个接入的可引导设备的引导扇区。它所找到的包含有效的引导记录的第一个引导扇区将被装载到内存中,并且控制权也将从引导扇区转移到此段代码。
引导扇区是引导加载器真正的第一阶段。
大多数 Linux 发行版本使用的引导加载器有三种:GRUB、GRUB2 和 LILO。GRUB2 是最新的,也是相对于其他老的同类程序使用最广泛的。
引导装载程序
GRUB2 : 第二版大一统引导装载程序(GRand Unified BootLoader,Version 2)
GRUB2 是一个用于计算机寻找操作系统内核并加载其到内存的智能程序。
GRUB2 被设计为兼容操作系统多重引导规范,它能够用来引导不同版本的 Linux 和其他的开源操作系统;它还能链式加载专有操作系统的引导记录。
GRUB 能够通过文件 /boot/grub/grub.conf 进行配置。
GRUB2 能够通过文件 /boot/grub2/grub.conf 进行配置。
GRUB 现在已经逐步被弃用,在大多数现代发行版上它已经被 GRUB2 所替换,GRUB2 是在 GRUB 的基础上重写完成。
两个 GRUB 的最主要作用都是将内核加载到内存并运行。两个版本的 GRUB 的基本工作方式一致,其主要阶段也保持相同,都可分为 3 个阶段。在本文将以 GRUB2 为例进行讨论其工作过程。
GRUB 或 GRUB2 的配置,以及 GRUB2 的命令使用均超过本文范围,待续....
阶段 1
MBR:主引导记录(Master Boot Record)
如上文 POST(上电自检)阶段提到的,在 POST 阶段结束时,BIOS 将查找在接入的磁盘中查找引导记录,其通常位于 MBR,它加载它找到的第一个引导记录中到内存中,并开始执行此代码。
引导代码(及阶段 1 代码)必须非常小,因为它必须连同分区表放到硬盘的第一个 512 字节的扇区中。在传统的常规 MBR 中,引导代码实际所占用的空间大小为 446 字节。这个阶段 1 的 446 字节的文件通常被叫做引导镜像(boot.img),其中不包含设备的分区信息,分区是一般单独添加到引导记录中。
由于引导记录必须非常的小,它不可能非常智能,且不能理解文件系统结构。因此阶段 1 的唯一功能就是定位并加载阶段 2 的代码。为了完成此任务,阶段2 的代码必须位于引导记录与设备第一个分区之间的位置。在加载阶段 2 代码进入内存后,控制权将由阶段 1 转移到阶段 2。
阶段 2
如上所述,阶段 2 的代码必须位于引导记录与设备第一个分区之间的位置。该空间由于历史上的技术原因而空闲。
第一个分区的开始位置在扇区 63 和 MBR(扇区 0)之间遗留下 62 个 512 字节的扇区(共 31744 字节),该区域用于存储阶段 2的代码镜像 core.img 文件。该文件大小为 25389 字节,故此区域有足够大小的空间用来存储 core.img。
因为有更大的存储空间用于阶段 2,且该空间足够容纳一些通用的文件系统驱动程序,如标准的 EXT 和其它的 Linux 文件系统,如 FAT 和 NTFS 等。GRUB2 的 core.img 远比更老的 GRUB1 阶段 2 更复杂且更强大。这意味着 GRUB2 的阶段 3能够放在标准的 EXT 文件系统内,但是不能放在逻辑卷内。故阶段 3的文件可以存放于 /boot 文件系统中,一般在 /boot/grub2 目录下。
注意 /boot 目录必须放在一个 GRUB 所支持的文件系统(并不是所有的文件系统均可)。阶段 2 的功能是开始执行存放阶段 3文件的 /boot 文件系统的驱动程序,并加载相关的驱动程序。
阶段 3
GRUB 阶段 3 所有的文件都已存放于 /boot/grub2 目录及其几个子目录之下。该阶段没有一个类似于阶段 1 与阶段 2 的镜像文件。相应地,该阶段主要需要从 /boot/grub2/i386-pc 目录下加载一些内核运行时模块。
GRUB 阶段 3 的主要功能是定位和加载 Linux 内核到内存中,并转移控制权到内核。内核的相关文件位于 /boot 目录下,这些内核文件可以通过其文件名进行识别,其文件名均带有前缀 vmlinuz。你可以列出 /boot 目录中的内容来查看操作系统中当前已经安装的内核。
GRUB2 跟 GRUB1 类似,支持从 Linux 内核选择之一引导启动。Red Hat 包管理器(DNF)支持保留多个内核版本,以防最新版本内核发生问题而无法启动时,可以恢复老版本的内核。默认情况下,GRUB 提供了一个已安装内核的预引导菜单,其中包括问题诊断菜单(recuse)以及恢复菜单(如果配置已经设置恢复镜像)。
阶段 3 加载选定的内核到内存中,并转移控制权到内核代码。
内核初始化
内核文件都是以一种自解压的压缩格式存储以节省空间,它与一个初始化的内存映像和存储设备映射表都存储于 /boot
目录之下。
在选定的内核加载到内存中并开始执行后,在其进行任何工作之前,内核文件首先必须从压缩格式解压自身。一旦内核自解压完成,则加载 systemd 进程(其是老式 System V 系统的 init 程序的替代品),并转移控制权到 systemd。
这就是引导过程的结束。此刻,Linux 内核和 systemd 处于运行状态,但是由于没有其他任何程序在执行,故其不能执行任何有关用户的功能性任务。
启动init进程
启动过程紧随引导过程之后,启动过程使 Linux 系统进入可操作状态,并能够执行用户功能性任务。
有两种启动方式:
- 老版本的init进程
- 新版本的systemd进程
init进程启动方式
初始化系统。
/sbin/init进程是系统其他所有进程的父进程,当它接管了系统的控制权先之后,它首先会去读取/etc/inittab文件来执行相应的脚本进行系统初始化,如设置键盘、字体,装载模块,设置网络等。主要包括以下工作:
1)、执行系统初始化脚本(/etc/rc.d/rc.sysinit),对系统进行基本的配置,以读写方式挂载根文件系统及其它文件系统,到此系统算是基本运行起来了,后面需要进行运行级别的确定及相应服务的启动。rc.sysinit所做的事情(不同的Linux发行版,该文件可能有些差异)如下:
(1)获取网络环境与主机类型。
首先会读取网络环境设置文件"/etc/sysconfig/network",获取主机名称与默认网关等网络环境。
(2)测试与载入内存设备/proc及usb设备/sys。
除了/proc外,系统会主动检测是否有usb设备,并主动加载usb驱动,尝试载入usb文件系统。
(3)决定是否启动SELinux。
(4)接口设备的检测与即插即用(pnp)参数的测试。
(5)用户自定义模块的加载。用户可以再"/etc/sysconfig/modules/*.modules"加入自定义的模块,此时会加载到系统中。
(6)加载核心的相关设置。按"/etc/sysctl.conf"这个文件的设置值配置功能。
(7)设置系统时间(clock)。
(8)设置终端的控制台的字形。
(9)设置raid及LVM等硬盘功能。
(10)以方式查看检验磁盘文件系统。
(11)进行磁盘配额quota的转换。
(12)重新以读取模式载入系统磁盘。
(13)启动quota功能。
(14)启动系统随机数设备(产生随机数功能)。
(15)清楚启动过程中的临时文件。
(16)将启动信息加载到"/var/log/dmesg"文件中。
当/etc/rc.d/rc.sysinit执行完后,系统就可以顺利工作了,只是还需要启动系统所需要的各种服务,这样主机才可以提供相关的网络和主机功能,因此便会执行下面的脚本。
2)、执行/etc/rc.d/rc脚本。该文件定义了服务启动的顺序是先K后S,而具体的每个运行级别的服务状态是放在/etc/rc.d/rc.d(=0~6)目录下,所有的文件均是指向/etc/init.d下相应文件的符号链接。rc.sysinit通过分析/etc/inittab文件来确定系统的启动级别,然后才去执行/etc/rc.d/rc*.d下的文件。
/etc/init.d-> /etc/rc.d/init.d
/etc/rc ->/etc/rc.d/rc
/etc/rc*.d ->/etc/rc.d/rc*.d
/etc/rc.local-> /etc/rc.d/rc.local
/etc/rc.sysinit-> /etc/rc.d/rc.sysinit
也就是说,/etc目录下的init.d、rc、rc*.d、rc.local和rc.sysinit均是指向/etc/rc.d目录下相应文件和文件夹的符号链接。我们以启动级别3为例来简要说明一下。
/etc/rc.d/rc3.d目录,该目录下的内容全部都是以 S 或 K 开头的链接文件,都链接到"/etc/rc.d/init.d"目录下的各种shell脚本。S表示的是启动时需要start的服务内容,K表示关机时需要关闭的服务内容。/etc/rc.d/rc.d中的系统服务会在系统后台启动,如果要对某个运行级别中的服务进行更具体的定制,通过chkconfig命令来操作,或者通过setup、ntsys、system-config-services来进行定制。如果我们需要自己增加启动的内容,可以在init.d目录中增加相关的shell脚本,然后在rc.d目录中建立链接文件指向该shell脚本。这些shell脚本的启动或结束顺序是由S或K字母后面的数字决定,数字越小的脚本越先执行。例如,/etc/rc.d/rc3.d /S01sysstat就比/etc/rc.d/rc3.d /S99local先执行。
3)、执行用户自定义引导程序/etc/rc.d/rc.local。其实当执行/etc/rc.d/rc3.d/S99local时,它就是在执行/etc/rc.d/rc.local。S99local是指向rc.local的符号链接。就是一般来说,自定义的程序不需要执行上面所说的繁琐的建立shell增加链接文件的步骤,只需要将命令放在rc.local里面就可以了,这个shell脚本就是保留给用户自定义启动内容的。
4)、完成了系统所有的启动任务后,linux会启动终端或X-Window来等待用户登录。tty1,tty2,tty3...这表示在运行等级1,2,3,4的时候,都会执行"/sbin/mingetty",而且执行了6个,所以linux会有6个纯文本终端,mingetty就是启动终端的命令。
除了这6个之外还会执行"/etc/X11/prefdm-nodaemon"这个主要启动X-Window
systemd进程启动方式
systemd 是所有进程的父进程。它负责将 Linux 主机带到一个用户可操作状态(可以执行功能任务)。systemd 的一些功能远较旧式 init 程序更丰富,可以管理运行中的 Linux 主机的许多方面,包括挂载文件系统,以及开启和管理 Linux 主机的系统服务等。但是 systemd 的任何与系统启动过程无关的功能均不在此文的讨论范围。
首先,systemd 挂载在 /etc/fstab 中配置的文件系统,包括内存交换文件或分区。据此,systemd 必须能够访问位于 /etc 目录下的配置文件,包括它自己的。systemd 借助其配置文件 /etc/systemd/system/default.target 决定 Linux 系统应该启动达到哪个状态(或目标态target)。default.target 是一个真实的 target 文件的符号链接。对于桌面系统,其链接到 graphical.target,该文件相当于旧式 systemV init 方式的 runlevel 5。对于一个服务器操作系统来说,default.target 更多是默认链接到 multi-user.target, 相当于 systemV 系统的 runlevel 3。 emergency.target 相当于单用户模式。
在
sysinit.target
的条件满足以后,systemd 接下来启动 basic.target
,启动其所要求的所有单元。 basic.target
通过启动下一目标态所需的单元而提供了更多的功能,这包括各种可执行文件的目录路径、通信 sockets,以及定时器等。
最后,用户级目标态(multi-user.target
或 graphical.target
) 可以初始化了,应该注意的是 multi-user.target
必须在满足图形化目标态 graphical.target
的依赖项之前先达成。
图 1 中,以 *
开头的目标态是通用的启动状态。当到达其中的某一目标态,则说明系统已经启动完成了。如果 multi-user.target
是默认的目标态,则成功启动的系统将以命令行登录界面呈现于用户。如果 graphical.target
是默认的目标态,则成功启动的系统将以图形登录界面呈现于用户,界面的具体样式将根据系统所配置的显示管理器而定。
参考链接:
https://www.cnblogs.com/QLinux/articles/2540304.html
http://www.cnblogs.com/bluestorm/p/5981435.html
https://www.linuxidc.com/Linux/2017-08/146494.htm