揭秘Linux启动的层层面纱,一文看懂从黑屏到界面的精彩之旅


从按下开机键到Linux系统界面显示,这中间究竟经历了怎样的过程?本文将为您一一揭开Linux启动的神秘面纱,详细剖析每个环节的工作原理,让你从内核出生到系统服务启动,一路见证这个过程的壮阔与精彩。


一、概述

Linux系统的启动过程大致可以分为以下几个阶段:

  1. 上电自检(POST)
  2. 基础输入输出系统(BIOS)
  3. 主引导记录(MBR)和引导加载程序(GRUB)
  4. 加载内核(Kernel)
  5. 初始化init进程
  6. 启动运行级别(Runlevel)

接下来,我们就一起走进每个阶段,深入探索其中的奥秘。


在这里插入图片描述


二、上电自检(POST)

上电后,首先是上电自检(Power-On Self-Test,POST)环节,主要工作是检查计算机硬件是否正常。

POST由主板上的BIOS芯片中的指令完成,它会逐一检查系统中的硬件设备,包括CPU、内存、硬盘等。

POST 工作流程如下

  • 当计算机加电时,BIOS 会首先进行加电自检 (POST),检查计算机硬件是否正常工作,例如 CPU、内存、硬盘等。
  • 如果硬件检测失败,BIOS 会发出警报或显示错误信息。
  • 如果硬件检测成功,BIOS 会继续执行启动过程。

三、基础输入输出系统(BIOS)

BIOS 是英文 Basic Input/Output System 的缩写,中文意思是基本输入输出系统。它是一段固化到计算机主板上的程序, 它负责管理计算机最基本的硬件设备,例如键盘、鼠标、显示器、硬盘等,并引导操作系统,提供系统设置选项,负责管理电源 。

1、BIOS 的功能和作用
  • 硬件检测和初始化,确保计算机硬件正常工作

    在计算机启动时,BIOS 会检测并初始化所有连接到主板的硬件设备,例如键盘、鼠标、显示器、硬盘等,确保这些设备能够正常工作。

  • 引导操作系统

    BIOS 会从硬盘或其他启动设备中加载操作系统内核,并将其传递给操作系统进行启动。

  • 提供系统设置选项

    BIOS 提供一些系统设置选项,例如启动顺序、日期和时间、硬件配置等,方便用户进行系统配置。

  • 管理电源

    BIOS 可以控制计算机的电源状态,例如开机、关机、休眠等,方便用户进行电源管理。


2、 BIOS 的类型
  • 传统 BIOS: 传统 BIOS 是使用 16 位代码编写的,它只支持 16 位 CPU 和 1MB 以下的内存。

  • UEFI BIOS: UEFI BIOS 是使用 32 位或 64 位代码编写的,它支持 32 位或 64 位 CPU 和更大的内存。


3、BIOS 的工作流程

Step1, 加电自检 (POST)过程

BIOS 系统存储于主板的ROM芯片上,计算机在开机时,会最先读取该系统,然后会有一个加电自检过程(按下电源开关后,BIOS检查设备,可以听到“滴”的一声就说明设备正常),这个过程其实就是检查CPU和内存,计算机最基本的组成单元(控制器、运算器和存储器)。


Step2, 加载 MBR

BIOS还有一个主要的功能就是存储了磁盘的启动顺序,BIOS会按照启动顺序去查找第一个磁盘头的MBR信息,并加载和执行MBR中的Bootloader程序,若第一个磁盘不存在MBR,则会继续查找第二个磁盘,一旦BootLoader程序被检测并加载内存中,BIOS就将控制权交接给了BootLoader程序。


四、主引导记录(MBR)和引导加载程序(GRUB)


1、MBR

MBR(Master Boot Record) 是主引导记录,是硬盘的第一个扇区,里面存储着少量启动代码和分区表信息。每个可启动的操作系统都需要在MBR或分区表中留有相应的引导代码。

MBR存储于磁盘的头部(它指的是硬盘的第一个扇区),大小为512bytes。

  • Boot Loader ,占用446字节,存储有操作系统(OS)相关信息,如操作系统名称,操作系统内核位置等,它的主要功能是加载内核到内存中运行。
  • Partition Table 分区表,占用64字节,每个主分区占用16字节(这就是为啥一块硬盘只能有4个主分区)
  • 分区表有效性标记占用2字节 (“55,AA”是分区表结束的标志)

在这里插入图片描述

对于Linux系统,MBR中的代码将会加载并运行GRUB(GRand Unified Bootloader)引导加载程序。GRUB提供了一个菜单,可以选择要启动的操作系统或内核版本。选择后,它会加载指定的内核映像到内存。


可以查阅GRUB的源码了解其工作原理:

// grub-core/kern/main.c
int main()
{
    /* 初始化GRUB环境 */
    grub_init_all();

    /* 显示GRUB菜单 */
    grub_menu_show_entry_sequence();

    /* 选择内核映像并加载到内存 */
    grub_linux_boot();
}

2、Boot Loader

Boot Loader,中文翻译为引导加载程序,是计算机启动过程中必不可少的程序,它很小但非常重要,负责将操作系统内核加载到内存中,并启动操作系统。


(1)、 Boot Loader 的功能
  • 加载操作系统内核到内存中

  • 启动操作系统

  • 提供一些系统设置选项

  • 管理启动过程


(2)、Boot Loader 的类型
  • 主引导记录 (MBR): MBR 是存储在硬盘第一个扇区上的引导程序,它负责加载第一个操作系统的引导扇区。

  • 引导扇区: 引导扇区是存储在每个分区上的引导程序,它负责加载操作系统的内核。

  • GRUB: GRUB 是一个通用的引导加载程序,它支持多种操作系统,例如 Linux、Windows、FreeBSD 等。

  • LILO: LILO 是另一个通用的引导加载程序,它主要用于 Linux 操作系统。


(3)、Boot Loader 的工作流程
  • 当计算机加电时,BIOS 会首先读取硬盘第一个扇区上的 MBR。

  • MBR 会加载第一个操作系统的引导扇区到内存中。

  • 引导扇区会加载操作系统的内核到内存中。

  • 操作系统内核会启动操作系统。


3、GRUB

GRUB (GRand Unified Bootloader) 是一个通用的引导加载程序,它支持多种操作系统,例如 Linux、Windows、FreeBSD 等。 GRUB 是目前最流行的引导加载程序之一,它被广泛应用于各种 Linux 发行版中。


(1)、GRUB 的功能
  • 加载操作系统内核到内存中

  • 启动操作系统

  • 提供一些系统设置选项

  • 管理启动过程

  • 支持多种操作系统

  • 支持多种文件系统

  • 支持多种硬件平台


(2)、GRUB 的工作流程
  • 当计算机加电时,BIOS 会首先读取硬盘第一个扇区上的 MBR。

  • MBR 会加载 GRUB 的第一个阶段到内存中。

  • GRUB 的第一个阶段会加载 GRUB 的第二个阶段到内存中。

  • GRUB 的第二个阶段会显示启动菜单,允许用户选择要启动的操作系统。

  • 用户选择要启动的操作系统后,GRUB 会加载该操作系统的内核到内存中。

  • 操作系统内核会启动操作系统。


(3)、GRUB 的配置

GRUB 的配置可以通过编辑配置文件进行。配置文件通常位于 /boot/grub/grub.cfg 文件中。

grub.conf:
    #boot=/dev/sda  

    default=0        #设定默认启动的title的编号,从0开始  
    timeout=5       #等待用户选择的超时时间  
    
    splashimage=(hd0,0)/boot/grub/splash.xpm.gz    #GRUB的背景图片  

    hiddenmenu     #隐藏菜单  

    title CentOS (2.6.18-194.el5PAE)      #内核标题  

    root (hd0,0)         #内核文件所在的设备  

    kernel /vmlinuz-2.6.18-194.el5PAE ro root=LABEL=/     #内核文件路径以及传递给内核的参数  

    initrd /initrd-2.6.18-194.el5PAE.img                            #ramdisk文件路径  

在/boot/grub/grub.conf中可以看到:

  • root (hd0,0) 这一行实际上是指定了/目录的所在的位置,但这个根并不是真正的根,而是/所在的位置,可以理解成/boot是处在(hd0,0)/boot,而这里的(hd0,0)指的是第一个磁盘的第一个分区。

  • GRUB不是通过文件系统来访问内核的,因为此时内核还没有启动,不存在文件系统,而是直接访问 第一个磁盘的第一个分区(通过MBR中的分区表来识别分区),而识别MBR中的分区的文件系统,则是由GRUB通过加载自身携带的系统文件来实现的,这些文件在/boot/grub目录中。

在这里插入图片描述


五、加载内核(Kernel)

内核是操作系统中最核心的部分,它负责管理计算机的硬件资源,为上层应用程序提供支持和服务。

在Linux系统中,内核是压缩后的vmlinuz文件,GRUB会将其加载并解压到内存中。内核启动后,会进行一系列的初始化操作,如探测硬件资源、设置终端、挂载根文件系统等。

// linux-x.x.x/init/main.c
int __init start_kernel()
{
    /* 初始化各种子系统,如体系结构、内存管理、调度器等 */
    setup_arch(&command_line);
    setup_memory();
    scheduler_init();
    ......

    /* 挂载根文件系统 */
    prepare_namespace();

    /* 启动init程序 */
    kernel_thread(kernel_init, NULL, CLONE_FS);

    return 0;
}

Kernel 内核是 Linux 操作系统最主要的程序,它负责管理系统资源和运行应用程序。 内核是操作系统的心脏,它控制着所有硬件和软件的交互。


(1)、 Kernel的功能
  • 进程管理: 内核负责创建、调度和终止进程。

  • 内存管理: 内核负责分配和管理内存。

  • 文件系统管理: 内核负责管理文件系统,例如创建、删除和访问文件。

  • 设备驱动程序: 内核负责管理设备驱动程序,以便操作系统能够使用硬件设备。

  • 网络管理: 内核负责管理网络连接,例如发送和接收数据包。

  • 安全: 内核负责保护系统免受安全威胁,例如病毒和黑客攻击。


(2)、 Kernel的结构

Linux 内核是一个单内核系统,这意味着它只有一个内核。

内核由以下几个主要部分组成:

  • 内核核心: 内核核心是内核最核心的部分,它负责管理系统资源和运行应用程序。
  • 设备驱动程序: 设备驱动程序负责管理硬件设备,以便操作系统能够使用硬件设备。
  • 文件系统: 文件系统负责管理文件,例如创建、删除和访问文件。
  • 网络协议栈: 网络协议栈负责管理网络连接,例如发送和接收数据包。

(3)、 Kernel工作流程
  • Kernel的文件很小,只保留了最基本的模块,并以压缩的文件形式存储在硬盘中,当GRUB将Kernel读进内存,内存开始解压缩内核文件。

  • 内核启动,在stage2这个步骤时,就将initrd(Initial RAM Disk) 文件拷贝到了内存中,这个文件是在安装系统时产生的,是一个临时的根文件系统(rootfs)。 initrd这个文件,装载了必要的驱动模块,当Kernel启动时,可以从initrd文件中装载驱动模块,直到挂载真正的rootfs,然后将initrd从内存中移除。

  • Kernel会以只读方式挂载根文件系统,当根文件系统被挂载后,开始装载第一个进程(用户空间的进程),执行/sbin/init,之后就将控制权交接给了init程序。


六、初始化init进程

内核启动后,会执行/sbin/init程序,该程序是所有其他进程的祖先进程。

Init 是 Linux 系统中最古老的进程,它的 PID 始终为 1。

Init进程会根据运行级别(runlevel)来决定启动哪些程序。

在大多数Linux发行版中,init程序是systemd,负责启动和管理整个系统。你可以在源码systemd/src/core/main.c中看到它的入口:

// systemd/src/core/main.c 
int main() {
    ......
    /* 初始化systemd管理器 */  
    r = manager_init();
    ......

    /* 启动监控循环,运行系统服务 */
    r = manager_run(m);
    ......
}

内核并加载进内存运行并以读写方式挂载完根文件系统后,执行第一个用户进程init,init首先运行/etc/init/rcS.conf脚本,如下图:
在这里插入图片描述


上图可以看到,init进程通过执行/etc/rc.d/rcS.conf首先调用了/etc/rc.d/rc.sysinit,对系统做初始化设置,这是真正的OS初始化脚本。

在这里插入图片描述


事实上init执行/etc/rc.d/rc.sysinit的初始化将会做很多设置:

1、获得网络环境
2、挂载设备
3、开机启动画面Plymouth(取替了过往的 RHGB)
4、判断是否启用SELinux
5、显示于开机过程中的欢迎画面
6、初始化硬件
7、用户自定义模块的加载
8、配置内核的参数
9、设置主机名
10、同步存储器
11、设备映射器及相关的初始化
12、初始化软件磁盘阵列(RAID)
13、初始化 LVM 的文件系统功能
14、检验磁盘文件系统(fsck)
15、设置磁盘配额(quota)
16、重新以可读写模式挂载系统磁盘
17、更新quota(非必要)
18、启动系统虚拟随机数生成器
19、配置机器(非必要)
20、清除开机过程当中的临时文件
21、创建ICE目录
22、启动交换分区(swap)
23、将开机信息写入/var/log/dmesg文件中

init执行完/etc/rc.d/rc.sysinit后,将会执行/etc/inittab来设定系统运行的默认级别:
在这里插入图片描述


七、启动运行级别(Runlevel)


Runlevel 是 Linux 系统中的一种概念,它表示系统的运行级别。

每个运行级别都定义了一组特定的系统服务和应用程序。

例如,运行级别 0 表示关机状态,运行级别 1 表示单用户模式,运行级别 2 表示多用户模式,运行级别 3 表示图形界面模式,运行级别 5 表示图形界面模式并启动 X Window System。


(1)、 Runlevel 的类型
  • 运行级别 0: 关机状态

  • 运行级别 1: 单用户模式

  • 运行级别 2: 多用户模式,没有图形界面

  • 运行级别 3: 多用户模式,有图形界面

  • 运行级别 4: 未使用

  • 运行级别 5: 多用户模式,有图形界面并启动 X Window System

  • 运行级别 6: 重启


(2)、Runlevel 的配置

Runlevel 的配置通常位于 /etc/inittab 文件中。 在 /etc/inittab 文件中,可以使用 id 字段指定默认的运行级别。 例如,以下代码指定默认运行级别为 3:

id:3:initdefault:

(3)、Runlevel 的切换

可以使用 init 命令切换运行级别。 例如,以下命令将系统切换到运行级别 1:

init 1

(4)、Runlevel 的作用

Runlevel 用于控制系统的运行状态。 例如,可以在系统启动时指定默认的运行级别,或者在需要进行系统维护时切换到单用户模式。

在systemd中,运行级别的概念已被target取代,通过target可以灵活地启动任意的程序。


八、总结

通过上述分析,我们从整体上把握了Linux系统启动的全过程。每个环节都扮演着至关重要的角色,缺一不可。Linux启动之所以如此复杂,是为了保证系统的稳定性和高效性。如果你有独特的见解和想法,欢迎在评论区与我分享交流。

  • 23
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

w风雨无阻w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值