参考文献

inside-the-linux-kernel
linux-kernel-map

The Linux Booting Process

BIOS and UEFI

  • 首先,系统启动后,BIOS(基本输入/输出系统)或 UEFI(统一可扩展固件接口)程序就会启动.通常,BIOS 包含获得对主机设备的初始访问的所有代码:
    • keyboard 键盘
    • display screen 显示屏
    • disk drives 磁盘驱动器
    • serial communications 串行通讯
  • 然而,一旦系统完全启动,大多数这些设备都会有专用的设备驱动程序接管.
  • BIOS 和 UEFI 是计算机用来启动操作系统 (OS) 的固件接口.然而,这两个程序在如何存储驱动器上和有关驱动器的元数据方面有所不同:
    • BIOS 使用主引导记录 (MBR)
      • MBR 代表主引导记录,负责加载和执行 GRUB 引导加载程序.
      • MBR 位于可启动磁盘的第一个扇区,通常为 /dev/hda/dev/sda ,具体取决于您的硬件. MBR 还包含有关 GRUB 或非常旧的系统中的 LILO 的信息.
    • UEFI 使用 GUID 分区表 (GPT)
  • 接下来,BIOS 或 UEFI 运行开机自检 (POST). POST 执行一系列任务:
    • 验证硬件组件和外围设备
    • 进行测试以确保计算机处于正常工作状态
  • 此外,如果此测试发现任何错误,通常会在屏幕上显示错误消息.如果测试未能检测到 RAM,POST 会触发蜂鸣声.
  • 最后,如果系统通过了POST,则表明启动过程进入下一阶段.

Boot Loader

  • BIOS 或 UEFI 已运行 POST 来检查机器的状态.接下来,BIOS/UEFI 根据系统配置选择启动设备.通常,有一个默认的启动顺序:

    • Hard drives 硬盘驱动器
    • USB drives USB 驱动器
    • CD drives CD驱动器
  • 当然,我们可以配置BIOS或UEFI以任意顺序选择启动设备.无论它们的顺序如何,计算机都会在这些设备中一一查找引导加载程序.

  • 事实上,BIOS 系统的引导加载程序位于引导设备的第一个扇区中;这是MBR.它占用磁盘上的前 512 个字节.另一方面,UEFI 系统将所有启动数据存储在 .efi 文件中.该文件位于 EFI 系统分区上,其中包含引导加载程序.

  • 值得注意的是,引导加载程序是加载操作系统的小程序.引导加载程序的主要工作是对内核执行三个操作:在磁盘上定位、插入内存以及使用提供的选项执行.

  • 以下是 Linux 系统的一些可用引导加载程序

    • LILO
    • SYSILINUX
    • GRUB2
  • 一般来说,一旦计算机在设备上找到引导加载程序,它就会运行它.因此,这会加载一个更大、更复杂的程序,最终启动我们的操作系统.

LILO
  • 最初,LILO(Linux Loader)是最广泛使用的 Linux 引导加载程序之一.然而,它已经失去了人们的青睐,因为它不支持多引导环境和 UEFI.此外,它对新文件系统的支持有限.
  • LILO 的开发人员正式于 2015 年 12 月停止了其开发和支持.因此,Linux Loader 很旧并且大部分已经过时.
SYSILINUX
  • 同样,SYSLINUX 是 Linux 操作系统的引导加载程序,它在 FAT 文件系统(典型的 Windows 系统)上运行.简而言之,它的目标是简化首次安装 Linux 的过程.
  • 此外,SYSLINUX 支持几种主要的文件系统:
    • FAT
    • ext2
    • ext3
    • ext4
GRUB2
  • 尽管有很多选择,但几乎所有(非嵌入式)现代 Linux 发行版都使用 GRUB(GRand Unified Boot Loader),因为它功能非常丰富

    • 启动多个操作系统的能力
    • 启动图形界面和基于文本的界面
    • 允许通过串行电缆轻松使用
    • 用于交互式配置的强大命令行界面
    • 基于网络的无盘启动
  • 目前,GRUB2 已经取代了其过去的版本 (GRUB),现在称为 GRUB Legacy.重要的是,我们可以使用以下命令检查系统中的 GRUB 版本

    1
    2
    $ sudo grub-install -V
    grub-install (GRUB) 2.04-1ubuntu26.17
  • GRUB2 在引导过程中做了什么:

    • 在启动时从 BIOS 或 UEFI 接管

    • 加载自身

    • 将 Linux 内核插入内存

    • 将执行移交给内核

  • 值得注意的是,GRUB 配置文件默认位于 /boot/grub

    1
    2
    3
    4
    5
    6
    7
    8
    $ ls -l /boot/grub/
    total 2376
    drwxr-xr-x 2 root root 4096 Jun 23 2021 fonts
    -rw-r--r-- 1 root root 712 Jun 23 2021 gfxblacklist.txt
    -r--r--r-- 1 root root 10497 Aug 30 17:18 grub.cfg
    -rw-r--r-- 1 root root 1024 Aug 30 17:17 grubenv
    drwxr-xr-x 2 root root 12288 Jun 23 2021 i386-pc
    -rw-r--r-- 1 root root 2395475 Aug 30 17:18 unicode.pf2
  • 最初,GRUB Legacy 的引导过程分为三个阶段:

    • Stage 1
    • Stage 1.5
    • Stage 2
  • 然而,对于 GRUB2,这些阶段不再存在.相反,它包含具有类似功能的各种 *.img 文件.

  • 此时,GRUB2 将内核插入到内存中,并将系统的控制权交给内核.

Kernel

  • 经过 BIOS 或 UEFI、POST 并使用引导加载程序启动内核后,操作系统现在控制对计算机资源的访问.

  • 这里,Linux 内核遵循预定义的过程:

    • decompress itself in place 就地解压
    • perform hardware checks 执行硬件检查
    • gain access to vital peripheral hardware 访问重要的外围硬件
    • run the init process 运行初始化进程
  • 在引导过程的此阶段,GRUB 选择的内核首先挂载 grub.conf 文件中指定的根文件系统.然后它执行 /sbin/init 程序,它始终是第一个被执行的程序.可以通过其进程 ID (PID) 来确认这一点,该 ID 应始终为 1.

Systemd

  • 内核启动 init 进程,该进程启动父进程.在这里,所有Linux进程的父进程是Systemd,它取代了旧的SysVinit进程.按照启动步骤,Systemd 执行一系列任务:
    • probe all remaining hardware 探测所有剩余硬件
    • mount filesystems 挂载文件系统
    • initiate and terminate services 启动和终止服务
    • manage essential system processes like user login 管理基本的系统流程,例如用户登录
    • run a desktop environment 运行桌面环境
  • 事实上,这些任务和其他任务允许用户与系统交互.最后,Systemd 使用 /etc/systemd/system/default.target文件来决定 Linux 系统启动的状态或目标.

Run Levels

  • 在Linux中,运行级别代表操作系统的当前状态.运行级别定义哪些系统服务正在运行.此前,SysVinit 通过数字来识别运行级别.但是,.target 文件现在取代了 Systemd 中的运行级别.

  • 此外,Systemd 在系统启动时默认激活 default.target 单元.让我们检查一下我们的默认目标:

    1
    2
    # systemctl get-default
    graphical.target
  • 现在,让我们看看运行级别数字和目标之间的联系:

    target run level 说明
    poweroff.target 0 关闭计算机
    rescue.target 1 启动救援 shell 进程
    multi-user.target 3 将系统配置为非图形(控制台)多用户环境
    graphical.target 5 建立具有网络服务的图形多用户界面
    reboot.target 6 重新启动机器
    emergency.target emergency 紧急运行级别

Linux内核相关命令

modinfo

lsmod

modprobe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
modprobe -h    
Usage:
modprobe [options] [-i] [-b] modulename
modprobe [options] -a [-i] [-b] modulename [modulename...]
modprobe [options] -r [-i] modulename
modprobe [options] -r -a [-i] modulename [modulename...]
modprobe [options] -c
modprobe [options] --dump-modversions filename
Management Options:
-a, --all Consider every non-argument to
be a module name to be inserted
or removed (-r)
-r, --remove Remove modules instead of inserting
--remove-dependencies Deprecated: use --remove-holders
--remove-holders Also remove module holders (use together with -r)
-w, --wait <MSEC> When removing a module, wait up to MSEC for
module's refcount to become 0 so it can be
removed (use together with -r)
--first-time Fail if module already inserted or removed
-i, --ignore-install Ignore install commands
-i, --ignore-remove Ignore remove commands
-b, --use-blacklist Apply blacklist to resolved alias.
-f, --force Force module insertion or removal.
implies --force-modversions and
--force-vermagic
--force-modversion Ignore module's version
--force-vermagic Ignore module's version magic

Query Options:
-R, --resolve-alias Only lookup and print alias and exit
-D, --show-depends Only print module dependencies and exit
-c, --showconfig Print out known configuration and exit
-c, --show-config Same as --showconfig
--show-modversions Dump module symbol version and exit
--dump-modversions Same as --show-modversions
--show-exports Only print module exported symbol versions and exit

General Options:
-n, --dry-run Do not execute operations, just print out
-n, --show Same as --dry-run
-C, --config=FILE Use FILE instead of default search paths
-d, --dirname=DIR Use DIR as filesystem root for /lib/modules
-S, --set-version=VERSION Use VERSION instead of `uname -r`
-s, --syslog print to syslog, not stderr
-q, --quiet disable messages
-v, --verbose enables more messages
-V, --version show version
-h, --help show this help

dmesg