分段(Segmentation) 和 分页(Paging) 是操作系统中管理内存的两种主要技术,它们通过不同的方式将进程的地址空间映射到物理内存,各有优缺点和适用场景。以下是它们的核心区别和特点:
1. 分段(Segmentation)
基本思想
- 将程序的地址空间划分为 逻辑段(如代码段、数据段、堆段、栈段等),每个段是 可变长度 的内存块。
- 段的大小由程序的实际需求决定(例如,代码段的大小取决于代码量)。
- 通过 段表(Segment Table) 记录每个段的基址(起始物理地址)和界限(长度)。
地址转换
- 逻辑地址 = 段号(Segment Number) + 段内偏移(Offset)。
- CPU 通过段号查询段表,找到段的基址和界限。
- 检查偏移是否越界(若
Offset ≥ 段长度
,触发 段错误)。 - 物理地址 = 段基址 + 偏移量。
- 检查偏移是否越界(若
特点
- 优点:
- 符合程序的逻辑视图(代码、数据、堆栈分离)。
- 支持动态内存分配(段长度可变)。
- 便于共享和保护(例如,代码段可标记为只读,多个进程共享)。
- 缺点:
- 外部碎片:频繁分配和释放不同大小的段会导致内存碎片,需通过紧凑(Compaction)解决。
- 内存利用率低:段需连续存储,大段可能难以分配。
典型应用
- 早期系统(如 x86 实模式),现代系统中常与分页结合使用(如 Linux 的代码段、数据段)。
2. 分页(Paging)
基本思想
- 将物理内存和逻辑地址空间划分为固定大小的 页(Page) 和 页帧(Page Frame)(如 4KB)。
- 通过 页表(Page Table) 记录逻辑页到物理页帧的映射。
- 操作系统管理页表,硬件(MMU)完成地址转换。
地址转换
- 逻辑地址 = 页号(Page Number) + 页内偏移(Offset)。
- CPU 通过页号查询页表,找到对应的物理页帧。
- 物理地址 = 页帧号 × 页大小 + 偏移量。
特点
- 优点:
- 无外部碎片:页大小固定,分配简单。
- 高效内存利用:支持非连续存储,可通过页表灵活映射。
- 支持虚拟内存:未使用的页可换出到磁盘(Swap)。
- 缺点:
- 内部碎片:最后一页可能未完全利用(如进程需 5KB,但页大小为 4KB,会浪费 3KB)。
- 页表开销大:大地址空间需多级页表或哈希页表(如 64 位系统)。
典型应用
- 现代操作系统(如 Linux、Windows)均采用分页机制,支持虚拟内存。
3. 分段 vs. 分页
特性 | 分段(Segmentation) | 分页(Paging) |
---|---|---|
划分单位 | 可变长度段(代码、数据、堆栈等) | 固定大小页(如 4KB) |
地址转换 | 段表(基址 + 界限) | 页表(页号 → 页帧号) |
碎片问题 | 外部碎片(需紧凑) | 内部碎片(最后一页未填满) |
内存连续性 | 段需连续存储 | 页可非连续映射 |
共享与保护 | 天然支持(段粒度) | 需显式标记页权限 |
硬件支持 | 需段寄存器(如 x86) | 需 MMU + TLB |
适用场景 | 逻辑隔离(如代码与数据分离) | 通用内存管理(虚拟内存、交换) |
4. 分段与分页的结合
现代操作系统(如 x86-64 的 Linux)通常 同时使用分段和分页:
- 分段:仅用于基础隔离(如区分内核/用户空间),实际地址转换依赖分页。
- 分页:主导内存管理,支持虚拟内存、按需分页、共享内存等高级功能。
示例(x86-64)
- 逻辑地址 → 分段(平坦模式,段基址为 0)→ 线性地址 → 分页(4KB 页)→ 物理地址。
(实际分段被弱化,分页是核心机制。)
5. 关键问题
为什么现代系统以分页为主?
- 解决碎片问题:分页无外部碎片,内部碎片可控。
- 简化内存管理:固定页大小比可变段更易分配。
- 支持虚拟内存:分页是交换(Swapping)和按需加载的基础。
分段未被完全淘汰的原因?
- 部分架构(如 x86)需分段实现特权级隔离(内核/用户模式)。
- 嵌入式系统中,分段可能更简单(如无 MMU 的设备)。
总结
- 分段:按逻辑划分内存,适合隔离与保护,但存在外部碎片。
- 分页:按固定大小划分内存,支持高效虚拟内存,但可能浪费少量空间。
现代操作系统通过 分页为主、分段为辅 的方式平衡性能与功能需求。