第五问:一个程序从点击到启动发生了什么?

简介: 一个可执行程序从用户点击启动到运行,经历了8个主要阶段:用户触发启动、操作系统查找文件、进程创建、可执行文件加载到内存、初始化程序上下文、执行程序入口点、程序运行和程序退出。涉及硬盘、内存、缓存等硬件交互。

第五问:一个程序从点击到启动发生了什么?

一个可执行程序(exe 文件)从用户双击启动到程序运行的过程可以分为以下8个主要阶段,下面结合硬盘、内存、缓存等机制,分阶段展开说明。


1. 用户触发启动

用户通过某种操作(如鼠标双击)触发程序启动,操作本质上通过输入设备将信号传递到 CPU 中的中断处理系统:

  • 鼠标操作
  • 鼠标信号通过 USB 或其他接口传递到 CPU 中的中断控制器。
  • 中断控制器触发操作系统事件(如鼠标点击事件)。
  • 操作系统响应
  • 操作系统捕获鼠标点击事件。
  • 图形界面处理模块(如 Windows 的桌面窗口管理器 DWM)识别到用户点击了某个 exe 文件的图标,调用相应的文件管理服务来处理启动请求。

2. 操作系统查找文件

操作系统通过文件系统模块定位exe文件,涉及硬盘与文件系统的交互:

  1. 路径解析
  • 如果是绝对路径,直接从根目录开始查找。
  • 如果是相对路径,操作系统会结合当前工作目录构造绝对路径。
  1. 文件系统访问
  • 文件系统(如 NTFS、ext4)查找目录项
  • 读取磁盘中存储的文件目录结构,找到 exe 文件的元数据(文件的起始地址、大小等)。
  • 硬盘读取文件元数据
  • 文件系统发出读取请求,经过 I/O 调度系统,硬盘控制器将元数据加载到内存中。
  1. 权限验证
  • 操作系统检查用户是否具有执行权限。

3. 进程创建

3.1 分配 PCB

操作系统分配一个进程控制块(PCB),包括以下信息:

  • 进程 ID。
  • 程序计数器(指向入口地址)。
  • 寄存器快照。
  • 虚拟内存表。
  • 打开的文件句柄列表等。

3.2 初始化地址空间

  • 操作系统为新进程分配一个独立的虚拟地址空间。
  • 虚拟地址空间划分为以下部分:
  • 代码段:存储程序的机器指令。
  • 数据段:存储全局变量和静态变量。
  • 栈段:为函数调用和局部变量分配。
  • 堆段:动态分配的内存区域。

4. 可执行文件加载到内存

4.1 解析可执行文件结构

以 Windows 为例,exe 文件使用 PE(Portable Executable)格式,操作系统会:

  • 读取文件头
  • 通过磁盘 I/O,从硬盘将文件头读取到内存缓存。
  • 解析 PE Header,提取代码段、数据段、入口点等信息。
  • 加载程序段
  • 将硬盘上的 .text(代码段)、.data(数据段)、.rdata(只读段)等映射到内存。

4.2 硬盘到内存的数据传输

数据加载涉及以下硬件:

  • 磁盘调度
  • 操作系统调用磁盘驱动,通过 SATA、NVMe 或其他接口读取文件。
  • DMA(Direct Memory Access)传输
  • 硬盘控制器通过 DMA 将文件块直接传输到物理内存,而无需 CPU 参与,提升效率。
  • 高速缓存
  • 读取数据可能先加载到 CPU 的三级缓存(L1/L2/L3)中,以加速后续访问。

4.3 动态链接库加载

  • 查找 DLL 文件路径
  • 操作系统从注册表、系统路径、程序目录等位置查找所需的 DLL 文件。
  • 加载 DLL 文件
  • 与加载 exe 文件类似,将 DLL 的各个段映射到内存。
  • 符号解析
  • 将程序中对外部函数的调用(例如 printf)绑定到 DLL 中对应函数的实际地址。

5. 初始化程序上下文

操作系统为程序配置运行环境,包括:

  1. 设置栈和堆
  • 栈空间通常从高地址向低地址分配。
  • 堆空间从低地址向高地址分配。
  1. 初始化寄存器
  • 程序计数器(EIP/RIP)指向入口地址。
  • 栈指针(ESP/RSP)指向栈顶地址。
  1. 运行 CRT(C 运行时库)初始化函数
  • 初始化全局变量和静态变量。
  • 构造 C++ 对象。

6. 执行程序入口点

CPU 开始执行程序的第一条指令:

  • CPU 取指令
  • 从入口点地址(RIP/EIP)开始,读取指令到 L1 指令缓存。
  • 指令解码与执行
  • 解码指令并通过寄存器、内存等完成操作。
  • 指令流水线
  • CPU 使用指令流水线机制并行处理多条指令,提升执行效率。

7. 程序运行

程序从入口函数(如 main)开始,按照编译好的指令顺序执行:

  1. 内存访问
  • 虚拟地址通过 MMU(内存管理单元)转换为物理地址。
  • 如果数据不在内存,触发页面调度,从磁盘中加载页面到内存。
  1. 缓存优化
  • 经常访问的数据会保存在 CPU 的高速缓存中(L1/L2/L3)。
  1. 系统调用
  • 程序需要访问文件、网络等资源时,会通过系统调用切换到内核模式。

8. 程序退出

当程序结束时:

  1. 释放资源
  • 操作系统回收堆栈空间、文件句柄等资源。
  1. 返回退出码
  • 将程序的退出状态返回给父进程。
  1. 销毁进程
  • 从调度队列中移除,释放 PCB 和相关内存。

硬件交互简要总结

阶段 描述
硬件交互 硬盘控制器通过 DMA 将文件元数据加载到内存。
文件查找 磁盘读取程序段,DMA 将数据传输到内存,CPU 通过缓存(L1/L2/L3)优化读取。
文件加载 MMU 实现虚拟地址到物理地址转换,未命中页表时触发页面调度加载。
内存管理 指令从内存加载到指令缓存,流水线和分支预测优化执行速度。
CPU 执行 系统调用通过中断与设备驱动程序交互,如文件读写通过硬盘控制器完成。

图形说明

相关文章
|
开发工具 C语言 git
Vcpkg 的安装与使用
Windows 下 Vcpkg 的安装与使用
1945 0
Vcpkg 的安装与使用
|
10月前
|
人工智能 Cloud Native Java
2025 开源之夏开启报名|AI + 云原生,10个开源项目、24个课题任您挑选
“开源之夏”是由中国科学院软件研究所发起的暑期活动,旨在鼓励高校学生参与开源软件开发与维护。活动联合各大开源社区提供项目任务,面向全球年满18周岁的高校学生开放报名。每位学生最多可申请一个项目。阿里云云原生提报了包括Apache Dubbo、RocketMQ、Seata等在内的10个开源项目共24个课题,涵盖技术优化、功能实现及AI应用等领域。活动流程包括选题、申请、开发与结项考核,具体信息可访问官网了解。
2831 32
|
监控 安全 网络协议
MITM攻击以及如何预防?
【8月更文挑战第31天】
396 1
|
移动开发 前端开发 Java
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
JavaFX是Java的下一代图形用户界面工具包。JavaFX是一组图形和媒体API,我们可以用它们来创建和部署富客户端应用程序。 JavaFX允许开发人员快速构建丰富的跨平台应用程序,允许开发人员在单个编程接口中组合图形,动画和UI控件。本文详细介绍了JavaFx的常见用法,相信读完本教程你一定有所收获!
13428 5
Java最新图形化界面开发技术——JavaFx教程(含UI控件用法介绍、属性绑定、事件监听、FXML)
|
网络协议 算法 网络性能优化
|
Java 编译器
Java中的return语句深入解析
Java中的return语句深入解析
946 0
|
存储 安全 固态存储
计算机启动:从插上电源到操作系统启动的全过程
当我们插上电源,计算机从休眠状态苏醒,直至操作系统完全启动,这一系列复杂的过程涉及到硬件和软件的多个层面。本文将详细解析计算机插上电源后操作系统所做的工作,揭示这一过程的技术细节。
1010 6
|
存储 缓存 JSON
详解HTTP四种请求:POST、GET、DELETE、PUT
【4月更文挑战第3天】
74185 5
详解HTTP四种请求:POST、GET、DELETE、PUT
|
NoSQL Linux 程序员
Linux objdump命令:深入解析与实战应用
`objdump`是Linux下的反汇编工具,用于将二进制文件转换为汇编代码,便于理解程序底层。它可以反汇编目标文件、可执行文件和库,支持多种参数,如显示符号表(-t)、反汇编代码(-d)、源代码与汇编混合视图(-S)。在实践中,结合-g编译选项和特定段(-j)反汇编,能辅助调试和分析。使用时注意包含调试信息,选择适当参数,并与其他工具(如gdb)配合使用。

热门文章

最新文章