深入理解Linux启动过程 && 0号进程,1号进程

本文深入解析Linux系统的启动过程,从BIOS初始化到内核加载,再到init进程的启动。介绍了MBR、第一阶段及第二阶段引导程序的作用,以及内核自解压过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

深入理解Linux启动过程


Linux系统的启动过程由很多阶段组成,这篇博客从初始化引导程序到第一个用户空间应用程序探索Linux启动进程。

我们先从Linux启动的顶层视图开始分析,以便能有一个整体的认识。
这里写图片描述

当系统第一次启动或重启的时候,处理器将执行一个已知地方的代码。对应个人电脑,这个地方是存在主板上内存内的BIOS

当一个启动设备被发现,第一阶段引导程序被加载到RAM并执行。这一部分引导程序位于512字节的MBR镜像(MBR后面会讲到),他的作用是去加载第二阶段引导程序。

当第二阶段引导程序被加载进RAM并执行,启动界面将被显示,并且Linux和可选的初始磁盘(临时文件系统)被加载进内存。当镜像被加载以后,控制权从第二阶段引导程序传递到内核镜像。

内核镜像自解压和初始化。在这一步,第二阶段引导程序将检查系统硬件,枚举硬件设备,挂载主设备,加载必须的内核模块。

当这些完成时,用户空间的第一个程序(init)开始执行,这样就开始顶层系统初始化开始了。

上面这些就仿佛是Linux启动过程的一个外壳,接下来我们开始更深层次的探索启动进程的细节。


系统启动

首先BIOS组成是:

  1. 上电自检代码
  2. 运行服务

Linux从0xffff0地址的BIOS开始启动,第一步是上电自检,上电自检的工作是检查硬件,第二步是枚举和初始化本地设备。

上电自检后,上电自检代码就从内存中被清除了,运行服务被保留并且对目标操作系统仍然有效。

要引导一个操作系统,BIOS运行时会按照CMOS的设置定义的顺序来搜索处于活动状态并且可以引导的设备(可以是软盘,CD-ROM,硬盘的分区,网络上的设备或者U盘)。

Linux一般从MBR包含初级引导程序的硬盘启动。MBR是一个512字节的扇区,位于硬盘的第一扇区(0道0柱1扇区)。在MBR被加载到RAM中后,由BIOS去控制它。


第一阶段引导程序

初级引导程序位于512字节的MBR镜像。
MBR镜像由一个小型分区表和代码组成。

前446字节是初级引导程序代码,包括执行代码和错误信息。

接下来的64字节是一个分区表,包含4个16字节的分区记录。

MBR最后的两字节定义了一个magic数字(0xaa55)。这个magic数字用来校验检查MBR。

这里写图片描述

初级引导程序主要就是找到并且加载第二阶段引导程序。其通过分区表寻找一个活动的分区。在找到一个活动的分区表后,其将扫描剩余的分区确定它们不是活动的。当这些被确定后,活动分区的启动启动记录将从设备加载到RAM并且执行。


第二阶段引导程序

第二阶段引导程序其实叫着内核引导程序更加合适。因为其任务就是加载Linux内核和可选的初始磁盘。

随着第二阶段被加载,CRUB会根据需求显示一个可用的内核列表(定义在/etc/grub.con,以及/etc/grub/menu.lst和/etc/grub.conf的软连接)。你可以选中一个内核,并且可以用附加的内核参数改进它。

第二阶段引导程序被加载进内存后,将查询文件系统,加载默认内核镜像和initrd镜像到内存。当所有镜像准备好后,将从第二阶段跳转到内核镜像。


内核

随着内核镜像加载到内存并且从第二阶段引导程序获得控制权,内核阶段开始了。内核镜像不是一个可以执行的内核,而是一个被压缩的内核镜像。

在内核镜像的头部有一个小型程序routine,其做少量的硬件设置,然后自解压内核镜像并放到高端内存。然后routine将调用内核开始内核启动。


init进程 && 0号进程和1号进程的前世今生

init进程就是我们常说的1号进程。

说到1号进程,就不得不说一下1号进程的前世今生!!!

Linux操作系统允许一个进程去创建新进程,新进程就是子进程,从而形成了进程树的结构模型

这棵大树的树根是系统自动构造的,就是内核态下执行的0号进程,0号进程是所有进程的祖先!!

有些同学会说 那我用过pstree命令看到的树根明明是1号init进程啊。

其实这个问题很简单,咱们使用pstree去查看进程树,咱们是处在用户态去看进程,而0号进程是一个内核态进程。就像一颗大树,你能看见的只是树长在地上的东西,地底下的树根是看不见的。而1号进程就是在地上树的最底部,而0号进程是地下的树根。

整个进程创建的过程:0号进程->1号内核进程->1号用户进程(init进程)->getty进程->shell进程

我给大家画了一幅图,这幅图可以很好的让你明白这个过程。
这里写图片描述

注意:

1号内核进程调用执行init函数演变成1号用户态进程(init进程),这里前者是init是函数,后者是进程。

两者容易混淆,区别如下:

1.init()函数在内核态运行,是内核代码

2.init进程是内核启动并运行的第一个用户进程,运行在用户态下。

3.一号内核进程调用execve()从文件/etc/inittab中加载执行init函数,这个过程并没有使用调用do_fork(),因此两个进程都是1号进程。

4.孤儿进程被1号进程领养

<think>好的,用户现在问的是Linux0进程1进程。之前他们问过内核启动的应用程序的标准输入输出是否指向控制台,现在这个问题似乎是在深入进程管理的部分,尤其是系统启动时的进程。 首先,我需要回忆一下0进程1进程的基本概念。0进程是内核启动后创建的第一个进程,通常称为idle进程或swapper,主要负责CPU空闲时的调度。而1进程是init进程,是所有用户空间进程的祖先,负责启动系统服务和守护进程。 用户可能是在学习Linux系统启动过程,或者对进程管理感兴趣。他们可能想知道这两个进程的区别、作用以及它们在内核中的角色。需要确保回答结构清晰,分点说明,符合之前用户要求的格式。 接下来要检查之前的对话历史。之前的回答中,用户关注的是标准输入输出的指向,涉及到内核启动进程和用户态进程的区别。这次的问题同样涉及内核和用户态进程的起点,可能需要联系之前的回答,保持一致性。 需要注意用户可能存在的误解,比如混淆0进程1进程的功能,或者认为0进程是用户空间的进程。需要明确区分两者的不同:0进程是内核线程,没有用户空间,而1进程是第一个用户态进程。 另外,用户可能想知道如何查看这两个进程的信息,比如使用ps或top命令。可能需要提供一些实际的命令示例,比如查看0进程通常不在ps列表中,或者1进程的详细信息。 还要考虑到用户可能的后续问题,比如这两个进程如何协作,或者系统启动过程中它们的作用。因此,在回答中需要涵盖它们的关系,例如0进程创建1进程,之后由1进程接管系统初始化。 需要确保使用中文,结构清晰,分步骤解析,使用适当的技术术语但不过于晦涩。同时,按照之前的格式,使用分节和子标题,帮助用户逐步理解。 最后,检查是否有遗漏的关键点,比如0进程的创建时机、调度方式,以及1进程的不同实现(如systemd、init等)。这些内容可以增强回答的全面性,满足用户的学习需求。</think>### 分步解析与回答 Linux 系统中的 **0 进程**和 **1 进程**是系统启动进程管理的核心组件,二者在功能和作用上存在本质区别。以下是详细分析: --- ### 一、0 进程(PID 0) #### 1. 基本定义 - **名称**:通常称为 `swapper` 或 `idle` 进程。 - **存在形式**:是内核启动后创建的第一个“逻辑进程”,但**不占用进程描述符**(`task_struct`),本质上是一个**内核线程**。 - **生命周期**:从系统启动到关机一直存在,负责 CPU 空闲时的调度。 #### 2. 核心功能 - **CPU 空闲管理** 当所有可运行进程处于阻塞状态时,0 进程通过执行 `cpu_idle_loop()` 进入低功耗模式(如 `HLT` 指令),直到被中断唤醒。 ```c // 内核代码片段(kernel/sched/idle.c) void cpu_startup_entry(enum cpuhp_state state) { arch_cpu_idle_prepare(); cpuhp_online_idle(state); while (1) do_idle(); // 进入空闲循环 } ``` - **进程创建起点** 在系统启动阶段,0 进程通过 `kernel_init()` 函数创建 1 进程(`init`),之后自身退化为纯粹的调度占位符。 #### 3. 特性验证 - **不可见性**:`ps` 或 `top` 命令无法直接观察到 0 进程(某些系统可能显示为 `[swapper]`)。 - **内核符**:通过 `cat /proc/0/cmdline` 会返回空,因为其不属于用户空间进程。 --- ### 二、1 进程(PID 1) #### 1. 基本定义 - **名称**:传统名称为 `init` 进程,现代系统可能使用 `systemd`、`upstart` 等替代。 - **角色**:是内核启动后第一个**用户空间进程**,也是所有用户进程的**祖先进程**。 #### 2. 核心职责 - **系统初始化** 加载初始化脚本(如 `/etc/inittab`),启动关键服务(网络、日志、SSH 等)。 - **孤儿进程回收** 通过 `wait()` 系统调用回收被终止子进程的资源,防止僵尸进程累积。 - **运行级别管理** 控制系统的运行模式(如单用户模式、多用户模式),通过 `telinit` 或 `systemctl` 切换。 #### 3. 实现差异 - **传统 SysVinit** 基于 Shell 脚本的启动方式,逐级执行 `/etc/rc.d/rcX.d/` 中的脚本(`X` 为运行级别)。 - **Systemd** 并行启动服务,通过单元文件(`.service`)管理依赖关系,提供更快的启动速度和状态监控。 #### 4. 特性验证 - **进程树查看** 使用 `pstree -p` 可观察到 1 进程作为根节点: ``` systemd(1)─┬─sshd(1234)─┬─sshd(5678)───bash(5679) ├─nginx(2345)───nginx(2346) └─dockerd(3456)───containerd(3457) ``` - **状态检查** 通过 `systemctl status` 或 `cat /proc/1/status` 可查看详细状态。 --- ### 三、二者关系与协作 #### 1. 启动顺序 - **硬件启动 → 内核初始化 → 0 进程激活 → 创建 1 进程 → 用户空间初始化**。 - 0 进程在完成 1 进程创建后,仅负责空闲调度,不再参与其他任务。 #### 2. 权限与资源 - **0 进程**:以内核权限运行,直接管理硬件中断和调度器。 - **1 进程**:以 `root` 权限运行,但受用户空间限制(如 `capabilities` 机制)。 --- ### 四、常见问题与调试 #### 1. 如果 1 进程崩溃会怎样? - 内核会触发 `panic`,导致系统停机(通过 `reboot=` 参数可配置重启行为)。 现代 `systemd` 通过 `Restart=always` 策略增强容错性。 #### 2. 如何自定义 1 进程? - 通过内核启动参数 `init=` 指定自定义程序: ```bash # 在 GRUB 配置中修改 linux /boot/vmlinuz ... init=/bin/bash ``` 此配置会跳过常规初始化流程,直接启动 Bash(需谨慎使用)。 #### 3. 0 进程的负载如何查看? - 通过 `mpstat` 或 `/proc/stat` 观察 CPU 空闲时间: ```bash $ mpstat 1 Linux 5.15.0 ... (x86_64) 05/15/2024 09:00:00 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle 09:00:01 all 5.2 0.1 1.3 0.2 0.0 0.0 0.0 0.0 93.2 ``` `%idle` 列反映 0 进程的活跃程度。 --- ### 五、总结 - **0 进程**是内核调度机制的基石,负责空闲状态管理和进程创建起点。 - **1 进程**是用户空间的起点,承担系统初始化、服务管理和进程回收职责。 - 二者共同构成 Linux 进程树的“根”,但功能、权限和实现方式截然不同。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值