Linux 开机 + 进程创建 + fork + exec + 加载器

文章目录

  • 一、计算机上电最源头(还没操作系统)
  • 二、Linux 内核初始化阶段
  • 三、Linux 后续所有进程统一创建规则
  • 四、加载器理解
  • 五、完整全局流程串联

**一、**计算机上电最源头(还没操作系统)

1. 电脑通电,硬件固化的 BIOS/UEFI 先运行

2. BIOS/UEFI 本质就是硬件级加载器

3. 它把硬盘上的 Linux 内核镜像 读取、加载到内存

4. CPU 跳转执行内核代码,操作系统正式开始启动

二、Linux 内核初始化阶段

1. 内核自己初始化:内存管理、进程调度、驱动、文件系统、网络等

2. 内核不依靠 fork,手动在内核态创建出系统第一个用户态进程: init / systemd

3. 内核自己调用内核内部的加载器逻辑,给这个进程载入程序、环境、栈结构

4. 这个进程是所有用户进程的祖先,整个系统进程树从它开始衍生

唯一特例:第一个用户进程 是内核直接创建+加载,没有经历 fork

三、Linux 后续所有进程统一创建规则

除了第一个始祖进程,系统进程、后台服务、终端、命令、自己写的程序、子进程......

全世界所有后续进程,套路永远固定:先 fork ,再 exec

1. 第一步:调用 fork

核心作用:单纯创建一个全新的子进程

分配全新 PID

复制父进程的 PCB 进程描述符

复制/共享虚拟地址空间、页表

生成一个独立的进程结构体,操作系统调度队列里多了一个进程

⚠️ 关键:

fork 结束这一刻:

子进程只是父进程的复刻品,代码、数据、程序和父进程一模一样,还没有新程序。

只是多了一个「进程壳子」,没有换新内容。

2. 第二步:子进程立刻调用exec系列函数然后该函数内部进行execve 系统调用

(1).execve 是内核自带的一段加载器代码,它绝对不创建新进程

(2). 就在当前这个刚刚 fork 出来的子进程内部原地操作:

释放、清空自己原来从父进程复制来的:代码段、数据段、BSS、堆、共享库

从磁盘读取新的 ELF 可执行文件

解析程序头部,把代码段、数据段映射到当前进程虚拟地址空间

清零 BSS 段

重新构建用户态栈,把命令行参数、环境变量拷贝进去

找到程序入口 _start

跳转过去,开始执行新程序

fork:只负责「生孩子」,造出独立进程、PID、壳子

exec内核加载器:只负责「换脑子」,原地把这个进程里面的旧程序扔掉,重装新程序,不

生新进程

四、加载器理解

1.内核加载器(exec)负责范围

(1).销毁进程旧的整片地址空间:旧代码、数据、堆、共享库、旧ld全部清空。

(2).解析ELF文件,映射程序自身代码段、数据段、BSS段到内存。

(3). 重建全新用户栈,完成命令行参数、环境变量的拷贝与传递,完成程序代码和数据的加载

(由内核完成,和ld无关)。

(4). 区分静态、动态链接程序,动态链接场景下负责加载ld-linux.so,并把执行权转交ld。

2.动态链接:内核加载器 + ld 分工

(1). ld-linux.so 是独立用户态程序,不属于操作系统内核。

(2).ld 只负责两件事:加载所有依赖的.so动态库、完成符号解析与运行时重定位。

(3). 动态链接完整流程:

exec内核加载器布置程序主体+参数环境+拉起ld → ld完成库加载和重定位 → ld跳转至程

序 _start ,用户代码开始运行。

3.静态链接执行流程

(1). 编译阶段已将库代码和程序代码合并,无需依赖外部动态库,不需要ld参与。

(2). 内核加载器完成内存映射、栈构建、参数环境传递后,直接跳转 _start 执行用户代码。

4.程序替换的本质:

调用exec做程序替换时,会彻底清空进程原有全部内存环境,包括旧程序、数据、动态库、

旧ld,再根据新程序类型,重新搭建全新的地址空间与运行环境。

5.为什么说每个进程最开始都是加载器

(1).进程fork诞生后,在执行业务代码前,必须先走加载流程。

(2).动态链接进程:内核加载器 → ld动态链接器 → 用户代码

(3).静态链接进程:内核加载器 → 用户代码

(4).本质:进程启动最先执行的是加载逻辑,而非自身业务代码,因此概括为每个进程最开始

都是加载器。

6.三种加载器最终区别

(1).BIOS/UEFI:硬件固件级小程序,负责加载操作系统内核。

(2).内核加载器(exec内部):内核代码一部分,负责程序替换、程序主体加载、参数环境

传 递、拉起ld。

(3).ld动态链接器:独立用户态程序,只负责依赖库加载和符号重定位。

7.总结

fork负责创建新进程容器,exec内核加载器负责替换程序与搭建运行基础环境,ld只负责动

态库与重定位,所有进程启动都必先经过加载阶段。

五、完整全局流程串联

上电 → 硬件BIOS/UEFI加载器 → 加载Linux内核 →

内核初始化 → 内核直接创建第一个用户进程(无fork) →

此后所有进程:

父进程fork生成子进程容器 → 子进程exec触发内核加载器 → 原地替换为新程序运行

相关推荐
AlfredZhao13 小时前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户97183563346619 小时前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪21 小时前
linux 拷贝文件或目录到指定的位置
linux
大树882 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠2 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush42 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5202 天前
Linux 11 动态监控指令top
linux
小宇宙Zz2 天前
Maven依赖冲突
java·服务器·maven
不会C语言的男孩2 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
古城小栈2 天前
Unix 与 Linux 异同小叙
linux·服务器·unix