进程地址空间
·
一、核心概念
- 虚拟地址:在Linux下,C/C++语言中所看到的地址(如变量地址、函数地址)全部是虚拟地址,而非物理内存地址。
- 物理地址:用户进程无法直接看到或操作,由操作系统统一管理,并通过页表将虚拟地址映射到物理地址。
- 进程地址空间:每个进程拥有自己独立的虚拟地址空间,由内核数据结构
mm_struct完整描述。
二、进程地址空间的布局(32位平台典型布局)
- 内核空间(1GB,高地址)
- 用户空间(3GB,低地址),从高地址到低地址依次为:
- 命令行参数与环境变量
- 栈区(向下生长)
- 共享区(动态库等)
- 堆区(向上生长)
- 未初始化数据段(BSS)
- 初始化数据段(数据段)
- 正文代码段(代码段)
该布局可通过代码打印各区域地址进行验证,地址值均为虚拟地址。
三、虚拟地址与父子进程的经典现象
- 现象:fork创建子进程后,父子进程打印同一个全局变量的地址相同,但值不同。
- 结论:
- 地址相同说明是虚拟地址相同;
- 值不同说明它们映射到了不同的物理地址;
- 证明了父子进程拥有独立的地址空间,且采用写时拷贝技术。
四、内核数据结构:mm_struct 与 vm_area_struct
mm_struct:每个进程的task_struct中有一个指向mm_struct的指针,用于描述该进程的完整虚拟地址空间。- 包含字段:代码段、数据段、堆、栈、参数段、环境段的起始与结束地址。
vm_area_struct:用于描述一个独立的虚拟内存区域(VMA),如堆、栈、共享库等。- 组织方式:
- 链表(
mmap)适用于VMA数量较少时; - 红黑树(
mm_rb)适用于VMA数量较多时,提高查找效率。
- 链表(
- 组织方式:
五、为什么要引入虚拟地址空间(解决的问题)
| 问题 | 说明 |
|---|---|
| 安全风险 | 若直接操作物理内存,任意进程可访问系统内存,易被恶意程序破坏。 |
| 地址不确定 | 程序每次加载到物理内存的位置不固定,导致编译时无法确定绝对地址。 |
| 效率低下 | 若以整个进程为单位进行内存交换(swap),开销大、效率低。 |
六、虚拟地址空间 + 分页机制带来的好处
-
内存保护
- 所有地址访问必须经过OS的页表映射,OS可控制访问权限,保护内核及其他进程数据。
-
解耦合
- 进程管理与内存管理分离,物理内存可任意位置加载进程数据,不影响进程自身视角。
-
延迟分配(按需分配)
malloc/new只在虚拟地址空间申请内存,物理内存可暂不分配;- 真正访问时才触发缺页中断,由OS分配物理内存并建立映射(用户和进程无感知)。
-
进程独立性
- 每个进程拥有独立的虚拟地址空间,互不干扰,增强了系统稳定性和安全性。
七、总结一句话
进程地址空间是操作系统为每个进程提供的独立虚拟内存视图,通过页表映射到物理内存,实现了内存保护、按需分配、进程隔离和高效管理,是现代操作系统稳定与安全的基础机制。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)