分段 vs 分页:内存管理的两大魔法!
按逻辑单元划分内存:代码段、数据段、堆栈段类似书籍的章节结构第一章:代码段第二章:数据段第三章:堆栈段固定大小的内存块:通常4KB(x86)虚拟页到物理页框的映射类似活页笔记本目录 = 页表页码 = 虚拟页号实际页 = 物理页框场景推荐方案原因现代通用操作系统纯分页虚拟内存支持,灵活性高嵌入式实时系统分段简单确定,开销小高性能计算分页+大页减少TLB缺失虚拟化环境嵌套分页减少虚拟机切换开销安全关键
·
当你的电脑同时运行十几个程序时,它们如何和谐共享有限的内存空间?为什么程序可以使用比物理内存更大的地址?这一切都归功于操作系统的分段和分页技术——内存管理的两大支柱!

一、内存管理:计算机的"房地产经纪人"
想象一个繁忙的城市:
- 🏢 建筑物 = 内存块
- 👨💼 居民 = 程序和数据
- 📐 分段 = 按功能划分区域(住宅区、商业区)
- 📄 分页 = 标准化公寓单元(统一户型)

二、分段:逻辑视角的内存管理
1. 什么是分段?
- 按逻辑单元划分内存:代码段、数据段、堆栈段
- 类似书籍的章节结构:
- 第一章:代码段
- 第二章:数据段
- 第三章:堆栈段

2. 分段地址转换

段寄存器示例:
mov ax, 0x1000 ; 设置数据段
mov ds, ax
mov si, 0x200 ; 偏移地址
mov al, [ds:si] ; 访问物理地址 0x1000*16 + 0x200 = 0x10200
3. 分段优缺点
| 优点 | 缺点 |
|---|---|
| 逻辑清晰,符合程序结构 | 内存碎片问题严重 |
| 自然的内存保护机制 | 内存分配不够灵活 |
| 简化共享(共享代码段) | 最大段大小受限 |
| 支持动态链接 | 需要连续物理内存 |
三、分页:物理视角的内存管理
1. 什么是分页?
- 固定大小的内存块:通常4KB(x86)
- 虚拟页到物理页框的映射
- 类似活页笔记本:
- 目录 = 页表
- 页码 = 虚拟页号
- 实际页 = 物理页框

2. 分页地址转换(32位系统)

3. 页表项结构
31-12 9-11 8 7 6 5 4 3 2 1 0
+-------------------+-----+----+----+----+----+----+----+----+
| 页框基址 | AVL | G | PS | D | A | PCD| PWT| U/S| R/W| P |
+-------------------+-----+----+----+----+----+----+----+----+----+
- P:存在位(1=在内存中)
- R/W:读写权限
- U/S:用户/超级用户
- A:访问位
- D:脏位(已修改)
4. 分页优缺点
| 优点 | 缺点 |
|---|---|
| 解决外部碎片问题 | 页表占用额外内存 |
| 支持虚拟内存 | 地址转换开销大 |
| 灵活的权限控制 | 可能引起内部碎片 |
| 内存分配更高效 | TLB未命中影响性能 |
四、分段 vs 分页:终极对决
| 特性 | 分段 🧩 | 分页 📄 |
|---|---|---|
| 划分单位 | 逻辑模块(代码/数据) | 固定大小页(通常4KB) |
| 碎片问题 | 外部碎片严重 | 只有内部碎片 |
| 地址转换 | 基址+偏移量 | 多级页表映射 |
| 内存共享 | 段级共享 | 页级共享 |
| 虚拟内存 | 不支持 | 核心支持 |
| 硬件支持 | 段寄存器 | MMU/TLB |
| 现代应用 | 基本淘汰 | 所有现代OS的核心 |
| 优势场景 | 嵌入式系统 | 通用计算系统 |
五、现代解决方案:段页式内存管理

x86架构实现:
- 逻辑地址 → 段基址 + 偏移 = 线性地址
- 线性地址 → 页表查询 → 物理地址
保护模式代码示例:
; 设置段描述符
mov eax, ds_base
mov ebx, ds_limit
mov ecx, 0x92 ; 数据段,可读写
call set_descriptor
; 设置页目录
mov eax, page_dir_base
mov cr3, eax ; 加载页目录基址
; 启用分页
mov eax, cr0
or eax, 0x80000000 ; 设置PG位
mov cr0, eax
六、分页进阶:多级页表与TLB
1. 64位系统的四级页表

2. TLB(转换后备缓冲器)

TLB性能影响:
七、动手实验:模拟地址转换
分页地址转换Python模拟
def page_translate(virtual_addr, page_table):
# 32位地址:前20位页号,后12位偏移
page_num = virtual_addr >> 12
offset = virtual_addr & 0xFFF
if page_num in page_table:
# TLB命中
frame = page_table[page_num]
physical_addr = (frame << 12) | offset
print(f"虚拟地址 0x{virtual_addr:08X} → 物理地址 0x{physical_addr:08X}")
return physical_addr
else:
# 触发缺页异常
print(f"缺页异常!页面 0x{page_num:05X} 不在内存中")
return None
# 测试
page_table = {0x1000: 0x300, 0x1001: 0x301} # 页表映射
page_translate(0x10001234, page_table) # 输出:虚拟地址 0x10001234 → 物理地址 0x3010234
分段地址转换模拟
def segment_translate(logical_addr, segment_table):
selector = logical_addr >> 16
offset = logical_addr & 0xFFFF
if selector in segment_table:
base, limit = segment_table[selector]
if offset <= limit:
physical_addr = base + offset
print(f"逻辑地址 0x{logical_addr:08X} → 物理地址 0x{physical_addr:08X}")
return physical_addr
else:
print(f"段越界错误!偏移 {offset} 超出段限制 {limit}")
return None
else:
print(f"无效段选择符:0x{selector:04X}")
return None
# 测试
segment_table = {0x10: (0x10000, 0xFFFF)} # 段基址0x10000,限制0xFFFF
segment_translate(0x10001234, segment_table) # 输出:逻辑地址 0x10001234 → 物理地址 0x11234
八、现代内存管理技术演进

九、总结:选择正确的内存管理
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 现代通用操作系统 | 纯分页 | 虚拟内存支持,灵活性高 |
| 嵌入式实时系统 | 分段 | 简单确定,开销小 |
| 高性能计算 | 分页+大页 | 减少TLB缺失 |
| 虚拟化环境 | 嵌套分页 | 减少虚拟机切换开销 |
| 安全关键系统 | 分段+分页 | 多层保护机制 |
💡 核心洞见:
- 分段提供逻辑隔离,分页提供物理灵活
- 现代操作系统主要使用分页
- TLB是分页性能的关键
- 段页结合提供最大灵活性
思考题:为什么64位系统基本放弃了分段机制?评论区分享你的见解!
🚀 动手实验:在Linux中查看分页信息:
# 查看页大小 getconf PAGESIZE # 查看内存映射 cat /proc/self/maps # 查看TLB状态 perf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses ls
理解分段和分页,你就掌握了操作系统内存管理的核心魔法!现在打开你的任务管理器,看看那些正在被精心管理的内存区域吧!
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐

所有评论(0)