引言
在学习 C/C++ 过程中,关于数据在内存中的存储,常看到如下图片:

实际物理内存是连续的存储单元,由操作系统内核统一管理,没有'代码段、堆、栈'这样的分区布局。这只是为进程设计的虚拟的地址空间。
什么是进程地址空间?
虚拟地址
通过代码示例可以感受:


定义全局变量 g_val,子进程中修改变量值,打印结果显示 g_val 在子进程和父进程中的地址一模一样,但结果不同。这说明打印出的地址不是物理地址,此时子进程和父进程各自有一个 g_val。这个地址就是虚拟地址。
进程地址空间
进程地址空间也叫虚拟地址空间,是操作系统为每个进程分配的一个独立的、连续的虚拟内存区域。该空间与物理内存不存在一一对应关系,而是通过内存管理单元 (MMU) 和页表机制实现动态映射。

以 32 位机器为例,这段虚拟内存区域的寻址能力为 2^32 字节(4GB),不等同于进程地址空间占 4GB 内存,其中有 1GB 为内核空间,剩下 3GB 为用户空间。用户空间又被细分为多个区域。
进程地址空间的管理
在 Linux 中,task_struct 内部存在一个 mm_struct 结构体指针,用于存储指定区域的起始值和终止值。这些值是映射后的虚拟地址。
struct mm_struct { /*...*/ struct vm_area_struct *mmap; /* 指向虚拟区间 (VMA) 链表 */ struct rb_root mm_rb; /* red_black 树 */ unsigned long task_size; /*具有该结构体的进程的虚拟地址空间的大小*/ /*...*/ // 代码段、数据段、堆栈段、参数段及环境段的起始和结束地址。 unsigned long start_code, end_code, start_data, end_data; unsigned long start_brk, brk, start_stack; unsigned long arg_start, arg_end, env_start, env_end; /*...*/ }







