目录
2.各个区域数据的管理------vm_area_struct(VMA)
一.前言
我们已经知道操作系统将各种程序描述成进程形式,再进行组织起来运行,那么进程里的数据是被如何管理的呢?
我们本篇来讨论操作系统怎么对进程数据进行管理的。当然管理仍然是先组织,再描述。
我们在学习编程语言时,学习过数据在内存中存储的形式:

实际中物理地址没有这样的区域划分,物理地址仅仅是连续的,并且交给操作系统统一管理的,区域划分是为进程设计的虚拟地址空间。
二.虚拟地址空间
1.定义:
每个程序运行时,都会拥有一套独有的、隔离的虚拟内存地址,进程只能操作这套虚拟地址,不能直接访问物理内存。
2.划分:
用户地址空间(3G):进程自身拥有,运行用户态代码,权限受限(无法访问硬件或内核资源)。
内核地址空间(1G):全局唯一,所有进程共享同一份内核虚拟地址,仅内核态可访问,存放操作系统核心数据(可访问硬件资源,执行敏感操作)。
3.与物理地址进行映射
虚拟地址空间通过页表和内存管理单元MMU机制与物理地址空间进行动态映射。
三.对虚拟地址空间的管理
内核通过一套数据结构 + 系统调用 + 硬件分页机制统一对虚拟地址进行管理,分为三层:描述整个地址空间、划分内存区域、页表虚实映射。
1.总体上描述------mm_struct
定义:每个进程 task_struct 里有成员 struct mm_struct *mm,代表完整虚拟地址空间。
内容:
计数:mm_users /mm_count(生命周期)
VMA 管理:链表 + 红黑树 + mmap_sem(管理所有虚拟分区)
分段地址:代码 / 数据 / 堆 / 栈边界
页表根 pgd:虚实映射硬件支撑
内存统计:rss、total_vm、swap_vm
全局链表节点 mmlist:内核统一管理全部进程 mm
现在我们主要认识的就是mm_struct记载虚拟地址空间内的各个数据地址起始和终止值,方便进程快速访问。
多个进程mm_struct管理:所有有效 mm_struct 通过全局双向链表统一串联管理;
2.各个区域数据的管理------vm_area_struct(VMA)
因为各个区域的数据的功能不同,所以使用多个VMA来分别描述。
结构:
struct vm_area_struct {
/* 1. 虚拟地址区间:左闭右开 [vm_start, vm_end) */
unsigned long vm_start;
unsigned long vm_end;
/* 2. 归属该VMA的地址空间 mm_struct */
struct mm_struct *vm_mm;
/* 3. 双索引:双向链表 + 红黑树,用于mm快速管理所有VMA */
struct vm_area_struct *vm_next, *vm_prev; // 双向链表,按地址升序
struct rb_node vm_rb; // 红黑树节点,用于地址快速查找
/* 4. VMA权限/属性标志位(核心) */
unsigned long vm_flags;
/* 5. 文件映射相关:文件对象 + 文件内页偏移 */
struct file *vm_file;
loff_t vm_pgoff; // 单位:页,文件映射起始偏移
/* 6. 匿名内存COW核心链表,fork写时复制依赖 */
struct anon_vma_chain *anon_vma_chain;
/* 7. VMA操作回调函数集:缺页、关闭、修改权限等 */
const struct vm_operations_struct *vm_ops;
/* 8. 私有数据,设备驱动自定义使用 */
unsigned long vm_private_data;
};
多个VAM管理形式:
当虚拟区间较少时采取单链表,由mmap指针指向这个链表;
当虚拟区间多时采取红黑树进行管理,由mm_rb指向这棵树;

四.虚拟地址与物理地址进行动态映射
1.什么是页表
页表就是内核维护的一张映射表:记录"虚拟页 → 物理页框"的对应关系,配合硬件 MMU 完成地址翻译。

特点:每个用户进程拥有一套页表,互不干扰
2.虚拟地址与物理地址进行动态映射过程举例
我们创建一个变量val,如何fork一个子进程,改变val的原来值,观察其地址变化

结果:

val值改变了,但是地址值没有变化!!!
我们使用映射过程来解释:
1.创建子进程时,系统会将父进程的所有数据拷贝一份给子进程,包括虚拟地址以及对应关系------页表,所以子进程会拥有相同的虚拟地址,页表的对应关系也没有改变。

2.子进程改变变量值,系统会重新申请一块空间给子进程的该变量,这时子进程的虚拟地址值不变,但是页表上对应的物理地址改变。

五.设计意义
1.合理规划内存:
1.按区域存放数据,防止进程使用混乱
2.可以清晰管理数据,提高效率
2.规避使用风险,保护物理内存
1.进程使用数据需要经过映射过程,这个期间,内核就可以对使用权限进行审查。
2.实现各个进程的物理内存隔离,防止进程访问不属于自己的物理空间。
3.降低系统的复杂程度
进程只与虚拟地址进行交互,对物理内存的操作由内核完成,互不干扰,各司其职,实现管理分层,降低了系统的复杂程度。