• Linux x86_64 BIOS 启动


    前言

    本文以 centos 6/7 (2.6.32/3.10.0 ),x86_64平台为例。

    固件保存在主板上的 ROM 中,是计算机上电后执行的第一段程序。固件启动阶段的核心功能包括硬件初始化、硬件自检和加载 bootloader,最终会把控制权转交给给 bootloader。
    固件启动阶段主要有两种启动方式:Legacy BIOS 和 UEFI。

    这篇文章描述了Linux x86_64 UEFI 启动过程:Linux x86_64 UEFI 启动,接下来描述Linux x86_64 UEFI 启动过程。

    VMware Workstation Pro安装虚拟机默认都是BIOS启动:
    在这里插入图片描述

    其启动过程如下:

    在这里插入图片描述
    详细过程:
    在这里插入图片描述

    一、BIOS简介

    在计算机领域,BIOS(Basic Input/Output System,基本输入/输出系统)是一种固件,用于为操作系统和程序提供运行时服务,并在引导过程(开机启动)中执行硬件初始化。BIOS固件预装在IBM PC或IBM PC兼容系统主板上,并存在于一些基于UEFI的系统中,以保持与不支持UEFI本机操作的操作系统的兼容性。这个名字起源于1975年CP/M操作系统中使用的基本输入/输出系统。最初专有于IBM PC的BIOS已被一些公司(如Phoenix Technologies)逆向工程,用于创建兼容系统。原始系统的接口成为事实上的标准。

    在旧版PC中,BIOS初始化和测试系统硬件组件(自检或POST),并从存储设备加载引导加载程序,然后初始化内核。在DOS时代,BIOS为键盘、显示器、存储和其他输入/输出(I/O)设备提供了BIOS中断调用,标准化了应用程序和操作系统的接口。更近期的操作系统在启动后不再使用BIOS中断调用。

    大多数BIOS实现都专门设计用于特定的计算机或主板型号,通过与各种设备特别是系统芯片组进行接口交互。最初,BIOS固件存储在PC主板上的ROM芯片中。在后期的计算机系统中,BIOS内容存储在闪存存储器中,因此可以在不移除主板上的芯片的情况下进行重写。这使得用户可以轻松更新BIOS固件,以添加新功能或修复错误,但也为计算机感染BIOS恶意软件提供了可能性。

    统一可扩展固件接口(UEFI)是传统PC BIOS的后继者,旨在解决其技术限制。自2019年起,所有面向英特尔平台的PC不再支持传统BIOS。

    二、MBR

    主引导记录(Master Boot Record,MBR)是位于计算机分区的固定磁盘或可移动驱动器等大容量存储设备的前几个扇区中的一种引导扇区类型,用于与IBM PC兼容系统及更高版本的系统一起使用。MBR的概念在1983年的PC DOS 2.0中首次公开引入。

    MBR保存了关于磁盘扇区(也称为"块")如何划分为分区的信息,每个分区理论上包含一个文件系统。MBR还包含可执行代码,用作已安装操作系统的加载程序,通常通过将控制权传递给加载程序的第二阶段或与每个分区的卷引导记录(Volume Boot Record,VBR)结合使用。这段MBR代码通常被称为引导加载程序。

    MBR中的分区表组织方式将分区磁盘的最大寻址存储空间限制为2 TiB(232 × 512字节)。采用32位算术或4096字节扇区来略微提高这个限制的方法没有得到官方支持,因为这将破坏与现有引导加载程序、大多数MBR兼容的操作系统和相关系统工具的兼容性,并在狭义的系统环境之外使用时可能导致严重的数据损坏。因此,基于MBR的分区方案正在逐步被GUID分区表(GUID Partition Table,GPT)方案取代。GPT可以与MBR共存,以提供对旧系统的某种有限的向后兼容性。

    MBR由位于驱动器的第一个扇区中的512字节组成(即MBR扇区位于磁盘的第一扇区,一个扇区512字节。)。

    一个经典的通用MBR的结构:
    在这里插入图片描述

    AddressDescriptionSize(bytes)
    0x0000 (0)Bootstrap code area446
    0x01BE (446)Partition entry №116
    0x01CE (462)Partition entry №216
    0x01DE (478)Partition entry №316
    0x01EE (494)Partition entry №416
    0x01FE (510)0x551
    0x01FF (511)0xAA1
    446 + 16 *4 + 1 + 1 = 512
    

    0~446 字节保存 bootloader;447~510 字节保存分区信息,共四个,每个 16 字节;511~512 字节保存启动签名,内容为 0xAA55,0xAA表明这是一个可启动设备。

    MBR 中最主要的功能就是存储启动引导程序。

    查看MBR的内容:

    # hexdump -C -n 512 /dev/sda
    00000000  eb 63 90 10 8e d0 bc 00  b0 b8 00 00 8e d8 8e c0  |.c..............|
    00000010  fb be 00 7c bf 00 06 b9  00 02 f3 a4 ea 21 06 00  |...|.........!..|
    00000020  00 be be 07 38 04 75 0b  83 c6 10 81 fe fe 07 75  |....8.u........u|
    00000030  f3 eb 16 b4 02 b0 01 bb  00 7c b2 80 8a 74 01 8b  |.........|...t..|
    00000040  4c 02 cd 13 ea 00 7c 00  00 eb fe 00 00 00 00 00  |L.....|.........|
    00000050  00 00 00 00 00 00 00 00  00 00 00 80 01 00 00 00  |................|
    00000060  00 00 00 00 ff fa 90 90  f6 c2 80 74 05 f6 c2 70  |...........t...p|
    00000070  74 02 b2 80 ea 79 7c 00  00 31 c0 8e d8 8e d0 bc  |t....y|..1......|
    00000080  00 20 fb a0 64 7c 3c ff  74 02 88 c2 52 be 05 7c  |. ..d|<.t...R..||
    00000090  b4 41 bb aa 55 cd 13 5a  52 72 3d 81 fb 55 aa 75  |.A..U..ZRr=..U.u|
    000000a0  37 83 e1 01 74 32 31 c0  89 44 04 40 88 44 ff 89  |7...t21..D.@.D..|
    000000b0  44 02 c7 04 10 00 66 8b  1e 5c 7c 66 89 5c 08 66  |D.....f..\|f.\.f|
    000000c0  8b 1e 60 7c 66 89 5c 0c  c7 44 06 00 70 b4 42 cd  |..`|f.\..D..p.B.|
    000000d0  13 72 05 bb 00 70 eb 76  b4 08 cd 13 73 0d 5a 84  |.r...p.v....s.Z.|
    000000e0  d2 0f 83 de 00 be 85 7d  e9 82 00 66 0f b6 c6 88  |.......}...f....|
    000000f0  64 ff 40 66 89 44 04 0f  b6 d1 c1 e2 02 88 e8 88  |d.@f.D..........|
    00000100  f4 40 89 44 08 0f b6 c2  c0 e8 02 66 89 04 66 a1  |.@.D.......f..f.|
    00000110  60 7c 66 09 c0 75 4e 66  a1 5c 7c 66 31 d2 66 f7  |`|f..uNf.\|f1.f.|
    00000120  34 88 d1 31 d2 66 f7 74  04 3b 44 08 7d 37 fe c1  |4..1.f.t.;D.}7..|
    00000130  88 c5 30 c0 c1 e8 02 08  c1 88 d0 5a 88 c6 bb 00  |..0........Z....|
    00000140  70 8e c3 31 db b8 01 02  cd 13 72 1e 8c c3 60 1e  |p..1......r...`.|
    00000150  b9 00 01 8e db 31 f6 bf  00 80 8e c6 fc f3 a5 1f  |.....1..........|
    00000160  61 ff 26 5a 7c be 80 7d  eb 03 be 8f 7d e8 34 00  |a.&Z|..}....}.4.|
    00000170  be 94 7d e8 2e 00 cd 18  eb fe 47 52 55 42 20 00  |..}.......GRUB .|
    00000180  47 65 6f 6d 00 48 61 72  64 20 44 69 73 6b 00 52  |Geom.Hard Disk.R|
    00000190  65 61 64 00 20 45 72 72  6f 72 0d 0a 00 bb 01 00  |ead. Error......|
    000001a0  b4 0e cd 10 ac 3c 00 75  f4 c3 00 00 00 00 00 00  |.....<.u........|
    000001b0  00 00 00 00 00 00 00 00  30 1c 0a 00 00 00 80 20  |........0...... |
    000001c0  21 00 83 aa 28 82 00 08  00 00 00 00 20 00 00 aa  |!...(....... ...|
    000001d0  29 82 82 35 70 05 00 08  20 00 00 00 20 00 00 35  |)..5p... ... ..5|
    000001e0  71 05 83 fe ff ff 00 08  40 00 00 f8 ff 05 00 00  |q.......@.......|
    000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
    

    三、Linux BIOS 启动

    bootloader 启动阶段的核心功能是加载内核和 initramfs,并将控制权交给内核。

    主要是:BIOS + MBR + grub2 和 UEFI + GPT + grub2

    这里只介绍 BIOS+MBR+grub2 启动方案,这种引导方式,固件 BIOS 从启动设备的第一个扇区读取 bootloader。

    过程如下:

    boot.img(mbr 446B)  =>  core.img(diskboot.img + kernel.img + *mod)==> /boot/grub2/grub.cfg ==> vmlinuz 和 initramfs
    

    上述 boot.img、core.img 都是 bootloader的一部分,他们被硬编码到启动盘上,不是以文件的形式存在于文件系统中。

    # cat /etc/centos-release
    CentOS Linux release 7.4.1708 (Core)
    
    # ls -l /boot/grub2/i386-pc/*.img
    -rw-r--r--. 1 root root   512 Dec  9  2021 /boot/grub2/i386-pc/boot.img
    -rw-r--r--. 1 root root 26676 Dec  9  2021 /boot/grub2/i386-pc/core.img
    
    # file /boot/grub2/i386-pc/boot.img
    /boot/grub2/i386-pc/boot.img: x86 boot sector; partition 4: ID=0xd4, starthead 205, startsector 4277266767, 0 sectors, code offset 0x63
    
    # file /boot/grub2/i386-pc/core.img
    /boot/grub2/i386-pc/core.img: data
    

    Grub由2个image和很多.mod文件组成:boot.img + core.img + .mod。其中boot.img大小固定为512Byte。

    Centos7系统/boot/grub2/i386-pc/*目录下存在2个image镜像文件,这些文件会被grub2-install命令安装到硬盘的相应位置。当BIOS执行完毕后,就会被加载并引导系统完成启动。

    备注:/boot/grub2/i386-pc/boot.img和/boot/grub2/i386-pc/core.img文件通过grub2相关程序转换后写入磁盘boot loader,而不是直接将源文件写入boot loader。

    LINUX引导过程包括三个阶段:
    (1) The BIOS stage.
    (2)The Boot loader stage.
    (3)The Kernel stage.
    如下图所示:
    在这里插入图片描述

    3.1 BIOS stage

    ROM中包含JUMP函数的形式的指令,告诉CPU启动BIOS。

    Linux的引导过程始于BIOS阶段。BIOS是安装在主板上的一个小型存储模块。BIOS使用存储在CMOS芯片中的信息,CMOS芯片是安装在主板上的另一个存储模块,其中包含有关系统硬件配置的信息。

    (1)BIOS执行电源自检(POST)-检查硬件可用性的过程。BIOS会向每个设备发送一个电脉冲。如果设备回应(ACK),则表示硬件工作正常且准备就绪。如果设备不回应(NACK),则将将其视为故障设备或从系统中移除的设备。BIOS会维护一个连接到计算机的设备列表。它会更新列表以适应任何新的硬件,并在下次启动时使用该列表。

    (2)如果BIOS在POST过程中发现任何错误,它会通过一系列的蜂鸣声或在屏幕上显示的文本消息通知用户。在这个阶段发生的错误几乎总是硬件问题。

    (3)激活安装在计算机中不同卡上的其他BIOS芯片-例如,SCSI(小型计算机系统接口)和图形卡通常都有自己的BIOS芯片。

    (4)它通过执行对每个内存地址的读/写测试来验证RAM。它初始化寄存器、电源管理和显示设置。

    (5)然后,BIOS查看在CMOS芯片中以特定顺序标识为启动设备的存储设备序列。BIOS将尝试从第一个设备开始启动序列。如果BIOS找不到启动设备,它将尝试列表中的下一个设备。如果在设备上找不到正确的文件,启动过程将停止。

    请注意:要使设备可引导,它必须在其第一个/最后一个扇区(取决于制造商,通常是硬盘的第一个扇区)中具有主引导记录(MBR),也称为引导扇区。您需要格式化磁盘以在其引导扇区中添加MBR。MBR的大小为512字节(一个扇区)。

    MBR包含以下详细信息:
    (1)主引导加载程序代码(446字节)。
    (2)分区表(64字节)。
    (3)魔数(2字节)。

    主引导加载程序代码:该代码提供引导加载程序信息以及实际引导加载程序代码在硬盘上的位置细节。这对CPU加载引导加载程序的第二阶段非常有帮助。

    分区表:64字节的数据,用于存储诸如每个分区的起始地址和结束地址、分区大小、分区类型(主分区、扩展分区、逻辑分区或交换分区)等信息。

    魔数:魔数用作MBR的验证检查。如果MBR损坏,可以使用魔数来恢复它。

    MBR无法处理超过2 TB容量的磁盘。MBR最多支持四个主分区 - 如果您需要更多分区,您必须将其中一个主分区设置为“扩展分区”,并在其中创建逻辑分区。每个分区在MBR中需要占用16个字节的空间,因此最多可以获得4个分区(16 * 4 = 64)。

    在现代计算机中,MBR已被UEFI(统一固件接口)取代。

    3.2 Boot Loader Stage

    在初始化第一个启动设备后,BIOS将控制权交还给CPU。现在,CPU将加载MBR并读取MBR的第一部分,以获取实际引导加载程序/第二阶段引导加载程序的位置。实际引导加载程序位于MBR之后硬盘的前30千字节,此空间用于存储文件系统驱动程序和模块;并加载到RAM中以读取其配置并显示引导菜单,以选择要加载到内存中的内核。

    两个最常用的Linux引导加载程序是:
    Linux Loader(LILO)和 Grand Unified Bootloader(GRUB)。

    大多数现代LINUX版本使用GRUB而不是LILO。

    GRUB的过程包括三个阶段,分别称为Stage 1、Stage 1.5和Stage 2。引导加载程序加载后,CPU可以访问磁盘和内存,并从磁盘上存储的/boot/grub/grub.conf配置文件中读取。它创建一个临时虚拟文件系统的镜像,称为INITRD或初始RAM磁盘,然后挂载INITRD镜像并加载内核。GRUB指定了一个分区,其中包含压缩的内核映像、必要的模块和initramfs(initrd)。
    如下图所示:
    在这里插入图片描述

    3.2.1 GRUB Stage

    3.2.1.1 Stage 1

    正如在BIOS POST部分提到的那样,在POST结束时,BIOS会搜索连接的硬盘以查找引导记录,通常位于主引导记录(MBR)中,它将第一个找到的引导记录加载到内存中,然后开始执行引导记录。引导代码,即GRUB2的第一阶段(stage 1),非常小,因为它必须适应硬盘上的第一个512字节扇区,同时还包括分区表。在经典的通用MBR中,用于实际引导代码的总空间为446字节。第一阶段的446字节文件名为boot.img,并不包含分区表,分区表是单独添加到引导记录中的。

    由于引导记录必须非常小,并且不具备理解文件系统结构的能力。因此,第一阶段的唯一目的是定位并加载第1.5阶段。为了实现这一点,GRUB的第1.5阶段必须位于引导记录本身与硬盘上第一个分区之间的空间中。在将GRUB第1阶段加载到RAM中后,第1阶段将控制权交给第1.5阶段。

    ├── 阶段1引导加载程序
    │         └── 主引导加载程序
    │         └── 存储在MBR的446字节内
    │         └── 扫描分区表并从活动分区加载Stage 1.5加载程序
    
    3.2.1.2 Stage 1.5

    如上所述,GRUB的第1.5阶段必须位于引导记录本身与硬盘上第一个分区之间的空间中。出于技术原因,这个空间在历史上被保留未使用。硬盘上的第一个分区从扇区63开始,而MBR位于扇区0,这样就留下了62个512字节扇区(31,744字节)用于存储core.img文件,即GRUB的第1.5阶段。core.img文件大小为25,389字节(不同的发行版大小不同),因此在MBR和第一个磁盘分区之间有足够的空间来存储它。

    由于第1.5阶段可以容纳更多的代码,因此它可以包含一些常见的文件系统驱动程序,例如标准的EXT和其他Linux文件系统、FAT和NTFS。GRUB2的core.img比旧版GRUB1的第1.5阶段更复杂且功能更强大。这意味着GRUB2的第2阶段可以位于标准的EXT文件系统上,但不能位于逻辑卷上。因此,第2阶段文件的标准位置是在/boot文件系统中,具体位置是/boot/grub2。

    请注意,/boot目录必须位于GRUB支持的文件系统上。并非所有文件系统都被支持。第1.5阶段的功能是开始执行所需的文件系统驱动程序,以在/boot文件系统中定位第2阶段文件并加载所需的驱动程序。

    ├── 阶段1.5引导加载程序
    │         └── 从/Boot目录加载阶段2引导加载程序
    │         └── 包含小二进制文件,这将有助于从引导分区加载阶段2
    │         └── 它可以识别文件系统,当启动分区高于1024个柱面或使用LBA模式时需要该系统
    
    3.2.1.3 Stage 2

    GRUB2的所有文件都位于/boot/grub2目录及其多个子目录中。与第1和第2阶段不同,GRUB2没有一个像样的映像文件。相反,它主要由运行时内核模块组成,这些模块根据需要从/boot/grub2/i386-pc目录加载。

    GRUB2的第2阶段的功能是定位并将Linux内核加载到RAM中,并将计算机的控制权交给内核。内核及其相关文件位于/boot目录中。内核文件可通过以vmlinuz开头的命名来识别。您可以列出/boot目录的内容,以查看系统上当前安装的内核。

    与GRUB1类似,GRUB2支持从一组可选的Linux内核启动。Red Hat软件包管理器DNF支持保留多个内核版本,以便在最新版本出现问题时,可以启动较旧的内核版本。默认情况下,GRUB提供已安装内核的预引导菜单,包括救援选项和(如果配置的话)恢复选项。

    GRUB2的第2阶段将选择的内核加载到内存中,并将计算机的控制权交给内核。

    ├── 阶段2引导加载程序或内核加载程序
    │         └── 在此阶段,用户可以将参数传递给内核进行加载。
    │         └── 第二阶段加载程序的主要功能是加载内核和initrd(initramfs)
    │         └── 加载默认内核映像和initrd映像
    

    3.2.2 安装GRUB文件

    执行以下shell:

    # grub-install /dev/sda
    

    在grub2软件安装完后,会在/usr/lib/grub/i386-pc/目录下生成很多模块文件和img文件,还包括一些lst列表文件。

    # ls /usr/lib/grub/i386-pc/*.mod | wc -l
    257
    
    # ls -1 -d /usr/lib/grub/i386-pc/*.lst
    /usr/lib/grub/i386-pc/command.lst
    /usr/lib/grub/i386-pc/crypto.lst
    /usr/lib/grub/i386-pc/fs.lst
    /usr/lib/grub/i386-pc/moddep.lst
    /usr/lib/grub/i386-pc/partmap.lst
    /usr/lib/grub/i386-pc/parttool.lst
    /usr/lib/grub/i386-pc/terminal.lst
    /usr/lib/grub/i386-pc/video.lst
    
    # ls -1 -d /usr/lib/grub/i386-pc/*.img
    /usr/lib/grub/i386-pc/boot_hybrid.img
    /usr/lib/grub/i386-pc/boot.img
    /usr/lib/grub/i386-pc/cdboot.img
    /usr/lib/grub/i386-pc/diskboot.img
    /usr/lib/grub/i386-pc/kernel.img
    /usr/lib/grub/i386-pc/lnxboot.img
    /usr/lib/grub/i386-pc/lzma_decompress.img
    /usr/lib/grub/i386-pc/pxeboot.img
    

    grub2将boot.img转换后的内容安装到MBR(VBR或EBR)中的boot loader部分,将diskboot.img和kernel.img结合成为core.img,同时还会嵌入一些模块或加载模块的代码到core.img中,然后将core.img转换后的内容安装到磁盘的指定位置处。

    安装grub2的过程大体分两步:一是根据/usr/lib/grub/i386-pc/目录下的文件生成core.img,并拷贝boot.img和core.img涉及的某些模块文件到/boot/grub2/i386-pc/目录下;二是根据/boot/grub2/i386-pc目录下的文件向磁盘上写boot loader。

    .img文件和boot loader的内容是不一致的,因为img文件还要通过grub2相关程序来转换才是真正的boot loader。

    在这里插入图片描述

    其过程如下:

    grub-install --> /usr/lib/grub/i386-pc/ --> /boot/grub2/i386-pc --> 磁盘boot loader
    
    3.2.2.1 boot.img

    在Legacy BIOS的启动模式下,boot.img是grub2第一个被运行的程序,它被写入到MBR(Master Boot Record)或分区的boot sector中,因为MBR的大小是512字节,所以boot.img总是512字节大小; 但是写入到MBR的内容和boot.img的内容并不完全相同, MBR的内容是boot.img经过转换后的内容;因为MBR中的内容除了包含code, 还有磁盘的分区信息。

    # stat -c "%s" /boot/grub2/i386-pc/boot.img
    512
    
    # file /boot/grub2/i386-pc/boot.img
    /boot/grub2/i386-pc/boot.img: x86 boot sector; partition 4: ID=0xd4, starthead 205, startsector 4277266767, 0 sectors, code offset 0x63
    

    boot.img功能很简单,主要是读取磁盘中core.img中的第一个扇区(sector)到内存中并执行相应的代码,因为仅有512B,boot.img不能够加载文件系统,并且只能从硬盘固定的位置加载。

    3.2.2.2 core.img

    core.img是GRUB2的核心,由 grub-mkimage 动态创建,包括了 diskboot.img、kernel.img 和一系列模块。通常core.img包含了足够的模块(modules)为了访问xfs/ext4文件系统/boot/grub2目录,并且从/boot/grub2下加载所有剩余的模块,这些模块包含了启动目录处理,加载操作系统等等功能。目前disk限制core.img安装必须小于32KB,core.img一般被安装在硬盘特殊区域:embedding area。

    core.img是动态生成的,路径为/boot/grub2/i386-pc/core.img,在安装grub时,boot.img会被拷贝到/boot/grub2/i386-pc目录下。

    Grub2认识并支持更多的文件系统,并且可以通过Grub2的主程序直接在文件系统中搜寻kernel文件:
    core.img 可以直接从文件系统中读取 grub.cfg,路径为 /boot/grub2/grub.cfg,根据 grub.cfg 文件读取加载内核和 initramfs,并将控制权交给内核。

    (1)diskboot.img
    diskboot.img 由 grub2-pc-modules 包提供,大小 512B,组成 core.img 的第一个扇区,功能是读取 core.img 的剩余部分(kernel)到内存中,并跳转到 kernel.img。

    当从硬盘启动的时候这是core.img第一个扇区(sector)的内容,主要功能是读取剩下的core.img到内存中并开始运行kernel.img。同样diskboot.img没有文件系统的功能,当读取剩余的core.img时候,依然从硬盘固定位置读取。

    (2)kernel.img
    kernel.img 由 grub2-pc-modules 包提供,大小 50K 左右,grub 的核心代码,包含了 GURB 的基本运行时的基础设备:设备和文件处理框架、环境变量、救援模式命令行解析器等。kernel.img 很少单独使用,一般会构建到 core.img 中(.text 和 .data 段)

    3.2.2.3 *.mod
    # ls /boot/grub2/i386-pc/*.mod | wc -l
    257
    

    /boot/grub2/i386-pc/目录下有许多.mod文件,大部分模块会被core.img在运行时自动动态加载,其中小部分被整合到core.img中,比如文件系统xfs.mod等。

    3.3 Kernel Stage

    以centos 6为例:

    一旦内核加载到内存中,它会解压缩initrd镜像(使用zlib压缩成zImage或bzImage格式)并进行挂载。内核使用INITRD镜像创建虚拟根文件系统(VFS)并运行LINUXrc程序。该程序为内核准备真实的文件系统。
    即内核使用Initial RAM Disk(initrd)建立一个临时根文件系统,直到安装了真正的文件系统。

    内核检查新的硬件并加载任何所需的设备驱动程序。使用initrd镜像中的程序(例如insmod和rmmod)来加载和卸载内核模块。然后,内核按照grub.conf文件中的指定,挂载实际的根文件系统,并卸载initrd镜像,并释放磁盘映像占用的所有内存。

    最后,它运行init进程。

    初始化进程(init)是由内核启动的第一个进程(初始化进程)。它是所有进程的父进程。init进程的PID(进程ID)始终为1。该进程持续存在直到计算机停机。它负责系统的整个状态。该进程的设置存储在其配置文件/etc/inittab中,它是一个初始化表,定义了系统程序的启动方式。init进程使用/etc/inittab文件中的参数加载其余的系统守护进程。

    备注:Centos 6 虚拟文件系统为initrd,呼叫第一个进程init;Centos 7 虚拟文件系统initramfs,呼叫第一个进程systemd。
    Centos 6 :

    $ cat /proc/1/comm 
    init
    

    Centos 7:

    # cat /etc/centos-release
    CentOS Linux release 7.4.1708 (Core)
    
    # cat /proc/1/comm
    systemd
    # readlink /proc/1/exe
    /usr/lib/systemd/systemd
    

    初始化进程会查看/etc/inittab文件来决定系统要引导到哪个Linux运行级别。总共有7个运行级别,编号从0到6。它们分别是:

    运行级别0:将系统停止运行。

    运行级别1:以单用户模式运行Linux,并提供命令行界面(CLI)。

    运行级别2:以多用户模式运行Linux,禁用网络,并提供CLI。

    运行级别3:以多用户模式运行Linux,启用网络,并提供CLI。

    运行级别4:默认情况下未定义,允许具有必要权限的用户通过编辑"/etc/inittab"文件定义自定义的运行级别。

    运行级别5:以多用户模式运行Linux,启用网络,并提供图形用户界面(GUI)和CLI。

    运行级别6:重新启动系统。

    centos 6 :

    $ cat /etc/inittab
    # inittab is only used by upstart for the default runlevel.
    #
    # ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
    #
    # System initialization is started by /etc/init/rcS.conf
    #
    # Individual runlevels are started by /etc/init/rc.conf
    #
    # Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf
    #
    # Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,
    # with configuration in /etc/sysconfig/init.
    #
    # For information on how to write upstart event handlers, or how
    # upstart works, see init(5), init(8), and initctl(8).
    #
    # Default runlevel. The runlevels used are:
    #   0 - halt (Do NOT set initdefault to this)
    #   1 - Single user mode
    #   2 - Multiuser, without NFS (The same as 3, if you do not have networking)
    #   3 - Full multiuser mode
    #   4 - unused
    #   5 - X11
    #   6 - reboot (Do NOT set initdefault to this)
    # 
    id:5:initdefault:
    

    初始化进程开始执行与所选运行级别相对应的脚本。脚本信息存储在/etc/文件夹中的不同文件夹中:

    /etc/rc0.d/ - 包含在运行级别0中运行的启动/停止脚本
    /etc/rc1.d/ - 包含在运行级别1中运行的启动/停止脚本
    /etc/rc2.d/ - 包含在运行级别2中运行的启动/停止脚本
    /etc/rc3.d/ - 包含在运行级别3中运行的启动/停止脚本
    /etc/rc4.d/ - 包含在运行级别4中运行的启动/停止脚本
    /etc/rc5.d/ - 包含在运行级别5中运行的启动/停止脚本
    /etc/rc6.d/ - 包含在运行级别6中运行的启动/停止脚本

    一旦初始化进程完成,init进程会运行另一个文件/etc/rc.local,其中包含在初始化进程或引导过程中运行的最后一批命令。一切完成后,控制权交还给内核。

    一旦内核获得控制权,它会启动多个"getty"实例,等待控制台登录,然后生成用户的shell进程,并提供用户提示符以进行登录。

    centos 7 (systemd 代替 inittab):

    # cat /etc/inittab
    # inittab is no longer used when using systemd.
    #
    # ADDING CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
    #
    # Ctrl-Alt-Delete is handled by /usr/lib/systemd/system/ctrl-alt-del.target
    #
    # systemd uses 'targets' instead of runlevels. By default, there are two main targets:
    #
    # multi-user.target: analogous to runlevel 3
    # graphical.target: analogous to runlevel 5
    #
    # To view current default target, run:
    # systemctl get-default
    #
    # To set a default target, run:
    # systemctl set-default TARGET.target
    #
    [root@localhost ~]# cat /etc/inittab
    # inittab is no longer used when using systemd.
    #
    # ADDING CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
    #
    # Ctrl-Alt-Delete is handled by /usr/lib/systemd/system/ctrl-alt-del.target
    #
    # systemd uses 'targets' instead of runlevels. By default, there are two main targets:
    #
    # multi-user.target: analogous to runlevel 3
    # graphical.target: analogous to runlevel 5
    #
    # To view current default target, run:
    # systemctl get-default
    #
    # To set a default target, run:
    # systemctl set-default TARGET.target
    #
    

    SysVInit 是Linux中经典的初始化进程。初始化进程依赖于各个服务在/etc/init.d目录安装相关脚本。此外,这些脚本必须支持标准的命令,如start(启动)、stop(停止)和status(状态)。这个init系统的主要特点之一是它是一个一次性的启动过程,启动后不再跟踪各个服务。可以使用service命令从终端运行这些init脚本。

    SystemD是一个近期的初始化系统,旨在取代SysVInit。事实上,大多数Linux发行版,如Debian和Red Hat,已经将SystemD作为默认的init系统。与SysVInit不同,SystemD在初始化完成后会作为一个守护进程持续运行。此外,它们还通过cgroups来主动跟踪服务。systemctl命令是用户与SystemD进行交互和配置的入口点。

    传统的SysVinit进程使用运行级别(如前面讨论中提到的),但Systemd引入了目标(targets)的概念,提供了对系统在引导和运行时行为的更灵活和精细的控制。

    参考资料

    https://www.linkedin.com/pulse/linux-boot-process-sandeep-sharma-p
    https://www.linkedin.com/pulse/linux-boot-procedure-sriram-ramanujam

    https://opensource.com/article/17/2/linux-boot-and-startup
    https://mp.weixin.qq.com/s/N_lSjtorg0Ho_hSBiM5uKA
    https://blog.csdn.net/Anhui_Chen/article/details/106988113
    https://www.cnblogs.com/chaplain/p/16167738.html
    https://www.wxtechblog.com/grub/grub-install

  • 相关阅读:
    Mycat实现单库水平分表、按月分表
    JDBC、ORM、mybatis之间的关系
    Python内置数据类型
    用Rust手把手编写一个Proxy(代理), TLS加密通讯
    【c语言基础题】— —第四版,可当作日常练习和期末复习,有奇效哟!
    Creo 9.0 基准特征:基准平面
    2022-11-14 mysql-loose scan
    2023第十二届中国智能产业高峰论坛
    Vue事件处理器:事件绑定基础、事件修饰符:stop、prevent、capture、self、once;
    记一次pdjs时安装glob出现,npm ERR! code ETARGET和npm ERR! code ELIFECYCLE
  • 原文地址:https://blog.csdn.net/weixin_45030965/article/details/139658111