首页/操作系统/03-memory/内存保护机制 🔗 在 Obsidian 中打开
操作系统 · 03-memory

内存保护机制

重要度 ⭐⭐⭐⭐⭐ 操作系统/内存管理基址寄存器界限寄存器页保护段保护
速查
内存保护确保进程只能访问自己的地址空间:基址-界限(物理地址 = 基址 + 逻辑地址、检查 逻辑 ≤ 界限);页表用 R/W、U/S、NX 等保护位;特权级规则 $\max(CPL, RPL) \leq DPL$

速查

项目
核心概念内存保护机制
关键公式物理地址 $=$ 基址 $+$ 逻辑地址
页表保护位R/W(读写)、U/S(用户/内核)、NX(不可执行)
特权级规则$\max(CPL, RPL) \leq DPL$

访问基址-界限寄存器

内存保护确保每个进程只能访问自己的地址空间,防止进程间互相干扰和恶意访问。保护的目标:①进程不能访问其他进程的内存;②进程不能访问内核内存(除非通过系统调用);③防止缓冲区溢出等安全漏洞。

基址-界限寄存器(Base and Limit)

最简单的内存保护机制:

┌─────────────────────────────────┐
│           CPU                   │
│  ┌─────────┐  ┌─────────┐      │
│  │基址寄存器│  │界限寄存器│      │
│  │(Base)   │  │(Limit)  │      │
│  └────┬────┘  └────┬────┘      │
└───────┼────────────┼───────────┘
        │            │
        ▼            ▼
   物理地址 = 基址 + 逻辑地址
   检查: 逻辑地址 ≤ 界限

物理内存:
┌─────────────────────────────────┐
│  操作系统                         │
├─────────────────────────────────┤ ← 基址=1000
│  进程A                           │
│  (逻辑地址0~500)                  │
├─────────────────────────────────┤ ← 基址+界限=1500
│  进程B                           │
└─────────────────────────────────┘

工作过程

  1. CPU 发出逻辑地址
  2. 检查:逻辑地址 $\leq$ 界限?否则越界中断
  3. 计算:物理地址 $=$ 基址 $+$ 逻辑地址
  4. 访问物理内存
优缺点优点:简单高效;缺点:不支持内存共享,不支持权限细分。

页式内存保护

页表项中的保护位

PTE结构:
┌──────────────────────────────────┐
│ 物理页框号(PFN)    │ 保护位 │标志│
├────────────────────┼───────┼───┤
│                    │ R/W/X │P  │
└────────────────────┴───────┴───┘
含义
R可读
W可写
X可执行
U/S用户 / 内核模式

保护检查

  1. 用户态访问内核页(U/S=0)→ 保护异常
  2. 写只读页(R/W=0)→ 保护异常
  3. 执行不可执行页(NX)→ 保护异常
  4. 权限合法 → 正常访问

NX 位(No-Execute)

  • 现代 CPU 支持的硬件级不可执行保护
  • 标记数据页为不可执行,防止代码注入攻击
  • x86-64 页表项第 63 位

段式与段页式内存保护

段表项中的保护信息

段表项:
┌────────┬────────┬────────┬────────┐
│ 段基址  │ 段界限   │ 保护位  │ 其他   │
└────────┴────────┴────────┴────────┘

段式保护检查

  1. 检查段是否存在
  2. 检查访问权限(读 / 写 / 执行)
  3. 检查特权级($CPL \leq DPL$)
  4. 检查偏移量 $\leq$ 段界限

段页式:两级保护

  1. 段级保护:检查段的权限和界限
  2. 页级保护:检查页的权限位
逻辑地址 → [段号|页号|偏移]
            │
            ▼
      段表查找 + 段保护检查
            │
            ▼
      页表查找 + 页保护检查
            │
            ▼
         物理地址

特权级保护(Ring)与 ASLR

x86 特权级

Ring 0 (内核态) ← 最高特权
Ring 1 (设备驱动)
Ring 2 (设备驱动)
Ring 3 (用户态) ← 最低特权

低特权级不能直接访问高特权级资源;系统调用提供从 Ring 3 到 Ring 0 的安全入口;调用门、中断门实现特权级切换。

缩写含义
CPL当前特权级(Current Privilege Level)
DPL目标特权级(Descriptor Privilege Level)
RPL请求特权级(Requested Privilege Level)
检查规则$\max(CPL, RPL) \leq DPL$

地址空间布局随机化(ASLR)

  • 随机化进程的内存布局(栈、堆、共享库位置),增加攻击难度
  • 随机化的区域:栈位置、堆位置、共享库加载地址、可执行文件基址
  • 防止攻击者预测目标地址,增加 ROP 等攻击的难度,需配合 DEP/NX 才更有效

实际应用与 MMU 保护异常

防止缓冲区溢出

  1. NX 位:数据页不可执行
  2. 栈保护:栈上插入金丝雀值(Canary)
  3. ASLR:随机化地址布局

进程隔离与内核保护

  • 每个进程独立的页表,进程间无法直接访问对方内存
  • 内核页的 U/S 位设为 0,用户态无法访问内核内存
  • 共享内存需要显式请求;系统调用是访问内核的唯一合法入口

MMU 保护异常

异常原因处理
段错误(SIGSEGV)访问无效地址终止进程
总线错误(SIGBUS)对齐错误终止进程
页保护异常写只读页COW 或终止
缺页异常页不在内存从磁盘加载

记忆卡片

基址-界限寄存器如何保护?
检查逻辑 ≤ 界限,否则越界中断;物理地址 = 基址 + 逻辑地址。
页表中有哪些保护位?
R/W(读写)、U/S(用户/内核)、NX(不可执行)。
x86 特权级与规则?
Ring 0 内核心 → Ring 3 用户态;$\max(CPL,RPL) \leq DPL$。
ASLR 是什么?
随机化栈、堆、共享库位置,配合 NX 使用,增加攻击难度。
NX 位的作用?
标记数据页不可执行,防止代码注入(x86-64 页表项第 63 位)。

交互动画 · 访问越界与权限检查

CPU 逻辑地址逻辑 500 保护检查≤界限 1000 物理地址基址+逻辑 保护异常越界中断
点击访问类型,观察保护检查结果(红色 = 保护异常)
物理地址 = 基址(1000) + 逻辑地址;逻辑地址必须 ≤ 界限
基址=1000、界限=1000:合法逻辑范围 [0, 1000],对应物理 [1000, 2000]。

相关知识点

paging-and-segmentation page-table-structure

↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。