虚拟内存、分页分段、页面置换算法
虚拟内存是一种内存管理技术,为每个进程提供独立的、连续的地址空间,这个地址空间可以大于物理内存。通过页表将虚拟地址映射到物理地址,实现内存的抽象和隔离。
虚拟地址 → MMU(内存管理单元)→ 页表查询 → 物理地址
如果页面不在物理内存中,触发缺页中断,操作系统从磁盘加载页面到内存。
| 特性 | 分页(Paging) | 分段(Segmentation) |
|---|---|---|
| 划分单位 | 固定大小的页(4KB、2MB) | 不固定大小的段(逻辑单元) |
| 地址空间 | 一维线性地址 | 二维地址(段号+偏移) |
| 用户可见性 | 对用户透明 | 用户可见(代码段、数据段) |
| 碎片问题 | 内部碎片(页内未用空间) | 外部碎片(段之间空隙) |
| 共享和保护 | 以页为单位 | 以段为单位(更符合逻辑) |
大多数现代操作系统(如Linux)主要使用分页机制,因为:
页表是虚拟地址到物理地址的映射表,记录每个虚拟页对应的物理帧号及访问权限。
32位系统,页大小4KB,需要1M个页表项,每个进程需要4MB连续内存存储页表,开销巨大。
将页表分成多级,只为实际使用的虚拟地址分配页表,节省内存。
TLB(Translation Lookaside Buffer)是页表项的缓存,命中时可直接获得物理地址,避免多次内存访问。
| 算法 | 思想 | 优点 | 缺点 |
|---|---|---|---|
| FIFO | 先进先出 | 简单 | 可能淘汰常用页,Belady异常 |
| LRU | 最近最少使用 | 性能好,接近最优 | 实现复杂,开销大 |
| LFU | 最不经常使用 | 考虑访问频率 | 早期频繁页难淘汰 |
| Clock | 近似LRU | 实现简单,性能接近LRU | 不如LRU精确 |
系统频繁发生缺页中断,大部分时间都在进行页面置换,而不是执行有效工作。表现为CPU利用率低但磁盘I/O频繁。
程序分配的内存无法释放或忘记释放,导致可用内存逐渐减少,最终可能导致程序崩溃或系统变慢。
内存屏障是一种同步原语,用于控制内存操作的顺序,防止编译器和CPU对内存访问进行重排序。
现代CPU和编译器会对指令重排序以提高性能,但在多线程环境下可能导致数据不一致。
volatile变量会自动插入内存屏障,保证可见性和有序性。
使用更大的页面大小(如2MB、1GB)替代标准的4KB页面。
可以通过/proc/sys/vm/nr_hugepages配置大页数量,或使用透明大页(THP)自动管理。
NUMA(Non-Uniform Memory Access)是一种内存架构,每个CPU有自己的本地内存,访问本地内存快,访问远程内存慢。
将文件或设备映射到进程的虚拟地址空间,通过内存访问的方式读写文件,避免read/write系统调用的数据拷贝。
调用mmap建立映射 → 访问映射区域触发缺页 → 操作系统从磁盘读取页面到页缓存 → 建立虚拟地址到物理页的映射 → 后续直接读写内存