内存管理(连续分配/重定位/碎片)

连续分配/动态分区/重定位/内部外部碎片,常考概念对比。

#resource / operating-system #type / concept #status / growing

[!info] related notes 操作系统 MOC 死锁 页面置换:LRU

内存管理

1) 内存管理要解决的问题

  • 分配与回收:高效利用物理内存
  • 地址转换:逻辑地址 → 物理地址
  • 保护与共享:进程间隔离,同时允许共享库
  • 扩充:虚拟内存,让程序可用空间 > 物理内存

2) 重定位(逻辑地址 → 物理地址)

  • 静态重定位:装入时完成,装入后不能移动
  • 动态重定位:运行时通过基址寄存器 + 限长寄存器完成(现代系统常见)
物理地址 = 基址寄存器值 + 逻辑地址

3) 连续分配

  • 固定分区:预先划分 → 内部碎片
  • 动态分区:按需分配 → 外部碎片

动态分区分配算法:

算法策略特点
First Fit找到第一个够大的空闲块快,但低地址碎片多
Next Fit从上次位置继续找分散碎片
Best Fit找最小的够大块碎片小但多
Worst Fit找最大的空闲块碎片大但少

4) 碎片(必背)

  • 内部碎片:分配多了用不完(如固定分区、页式分配的最后一页)
  • 外部碎片:空闲块总量足够,但不连续(如动态分区)

解决外部碎片:紧凑(compaction) 或改用非连续分配(分页/分段)。

5) 分页 vs 分段

维度分页(Paging)分段(Segmentation)
划分方式固定大小(如 4KB)按逻辑单位(代码段、数据段等)
碎片内部碎片外部碎片
地址结构页号 + 页内偏移段号 + 段内偏移
共享/保护不方便(一页可能混合内容)方便(按段共享)
现代系统主流方案通常与分页结合(段页式)

分页地址转换

逻辑地址 = 页号 p + 页内偏移 d
页表[p] = 物理帧号 f
物理地址 = f × 页大小 + d

6) 虚拟内存

允许程序使用比物理内存更大的地址空间。核心思想:

  • 只将活跃页面保留在内存中
  • 不活跃页面放在磁盘交换区(swap)
  • 访问不在内存的页面时触发缺页中断(page fault)

缺页处理流程

CPU 访问虚拟地址
  → MMU 查页表 → 该页不在内存(valid bit = 0)
  → 触发缺页中断
  → OS 选择牺牲页(若页框满)
  → 将牺牲页写回磁盘(若脏页)
  → 从磁盘加载目标页到空闲页框
  → 更新页表
  → 重新执行触发缺页的指令

7) TLB(Translation Lookaside Buffer)

页表在内存中,每次地址转换需两次内存访问(查页表 + 访问数据)。TLB 是页表的高速缓存:

CPU 产生虚拟地址
  → 查 TLB(硬件,极快)
    → 命中:直接得到物理帧号
    → 未命中:查内存页表,结果写入 TLB

TLB 命中率通常 > 99%,有效将地址转换开销降到接近一次内存访问。

8) 内存映射文件(Memory-Mapped Files)

将文件映射到进程的虚拟地址空间,通过内存操作实现文件读写:

void *addr = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, offset);
// 之后直接通过 addr 指针读写,OS 负责 page-in/page-out
munmap(addr, length);

优点:避免显式 read/write 系统调用,利用 OS 的页面缓存机制。

9) 交换(Swapping)

将整个进程从内存移到外存(swap out),需要时再移入(swap in)。

  • 代价高(进程的全部页面都要移动),现代系统更倾向于页面级别的虚拟内存。
  • 仍用于内存极度紧张时回收物理页框。

相关笔记

创建于 2026/3/16 更新于 2026/5/27