四大金刚
一个二进制文件运行起来需要四个核心部件: 可执行文件,操作系统(os),内存(ram),处理器(cpu)协同操作。
1. 可执行文件(二进制文件)
- 作用:程序的 “静态载体”,包含计算机可直接执行的机器指令(二进制代码)、数据(如常量、初始化变量)、以及用于加载的元信息(如文件格式、内存布局描述、入口点地址等)。
- 常见格式:Windows 的
.exe、Linux 的 ELF(Executable and Linkable Format)、macOS 的 Mach-O 等。这些格式规定了指令和数据的组织方式,让操作系统能正确解析并加载。
2. 操作系统(OS)
作用
:程序运行的 “管理者”,负责协调硬件资源并提供运行环境,核心功能包括:
- 加载程序:将可执行文件从磁盘读入内存,根据文件中的元信息(如段表)分配内存区域(代码段、数据段、栈、堆等),并设置权限(如代码段设为只读可执行)。
- 进程管理:为程序创建进程(或线程),分配进程控制块(PCB)记录进程状态(如 PID、寄存器值、内存映射等),并调度进程获得处理器时间。
- 资源抽象与分配:通过系统调用(如文件操作、内存分配)为程序提供统一的硬件访问接口,避免程序直接操作硬件。
- 内存管理:通过虚拟内存机制将程序的逻辑地址映射到物理内存,实现内存隔离(不同程序互不干扰)和高效利用(如内存分页、交换)。
3. 内存(RAM)
作用
:程序运行的 “临时数据空间”,用于存储程序执行过程中的指令和数据:
- 代码段(Text Segment):存放可执行文件中的机器指令,供处理器读取并执行。
- 数据段(Data Segment):存放初始化的全局变量、静态变量(编译时已知值)。
- BSS 段:存放未初始化的全局变量、静态变量(默认初始化为 0,由操作系统在加载时分配空间)。
- 栈(Stack):存储函数参数、局部变量、返回地址等(见前文详解)。
- 堆(Heap):动态分配的内存(如
malloc申请的空间),供程序运行时灵活使用。
4. 处理器(CPU)
作用
:程序执行的 “运算核心”,负责逐条执行内存中的机器指令:
- 通过程序计数器(PC) 指向当前要执行的指令地址,执行后自动更新为下一条指令地址。
- 通过寄存器暂存运算数据(如累加器、地址寄存器),加速指令执行(寄存器速度远快于内存)。
- 执行指令时涉及的运算(如加减、逻辑判断)、内存访问(如读数据、写结果)、跳转(如函数调用)等操作,均由 CPU 完成。
运行过程
- 启动程序:用户通过操作系统(如调用系统的shell函数)触发程序运行请求。
- 加载到内存:操作系统解析可执行文件(elf文件格式),根据其元信息在内存中分配空间(代码段、数据段、栈等),将文件中的指令和数据复制到对应内存区域。
- 创建进程:操作系统为程序创建进程,初始化进程控制块(PCB),设置程序入口点(第一条指令的内存地址)。
- 调度执行:操作系统将进程放入调度队列,当分配到 CPU 时间片时,CPU 从程序入口点开始执行指令:
- 从内存中读取指令到 CPU,解码后执行(如运算、读写内存、调用函数等)。
- 执行过程中动态使用栈(函数调用)和堆(动态内存),操作系统负责维护内存映射和权限。
- 终止程序:程序执行完
main函数(或调用exit)后,操作系统回收进程占用的内存、CPU 等资源,进程终止。
注意 :1.可执行文件是elf格式 启动阶段 操作系统为起分配 虚拟内存(连续)也就是在此时 堆和栈诞生(与程序的生命周期相同)其中堆需要可执行文件中具有申请堆操作 而 栈是与生俱来的。
2.程序启动的初期阶段(如创建进程、分配虚拟内存、设置堆栈)需要操作系统内核完成,因此代码运行在内核态。
3.虚拟内存加载到物理内存的过程是动态且按需发生的执行到哪加载到哪 cpu 只能处理实际地址的内容
4.启动程序的过程本质是将静态的可执行文件加载到系统中,并创建对应的进程