x86特权级:Ring 0、Ring 3 和 CPL、DPL
概要:介绍 x86 的特权级体系:Ring 0(内核态)与 Ring 3(用户态)的概念,以及 CPL(存放在 %cs 中)与 DPL(存放在段描述符中)的硬件实现和“门禁核验”规则。
1. Ring 0 和 Ring 3:CPU 的“阶级地位”
Intel 的 x86 架构本来设计了四个特权级别(Ring 0 到 Ring 3),数字越小,权力越大。但后来像 Linux 和 Windows 这些现代操作系统嫌麻烦,觉得四层太复杂了,干脆只用了最高和最低的两个级别:
- Ring 0(内核态):这就像是“上帝模式”或者系统里的“超级管理员”。运行在这个级别的代码(通常是操作系统内核、底层硬件驱动)拥有最高权限,可以直接操控各种硬件、管理所有内存。要是 Ring 0 的代码写飞了,那整个系统就直接蓝屏或者死机了。
- Ring 3(用户态):这就像是普通的“打工人”。咱们平时写的业务代码,或者跑的 QQ、浏览器,全都在 Ring 3 跑着。这个级别的权限被锁得死死的,不能直接碰硬件。如果 Ring 3 的程序想读写硬盘或者收发网络数据,必须老老实实地向 Ring 0 “打报告”(也就是发起系统调用),让 Ring 0 帮忙去做。
┌──────────┐
│ Ring 3 │ ← 普通用户程序(权限最低)
│ ┌──────┐ │
│ │Ring 0│ │ ← 操作系统内核(权限最高)
│ └──────┘ │
└──────────┘
2. CPL (Current Privilege Level):你手里拿的“当前门禁卡”
CPL 就是当前正在执行的代码的权限级别。
还记得咱们刚才说的 %cs 代码段寄存器吗?在保护模式下,%cs 寄存器最低的那两位(第 0 位和第 1 位)存放的就是 CPL。
- CPU 每执行一条指令,它都知道自己现在的 CPL 是几。
- 如果这两位是
00(也就是 0),说明当前代码正拿着 Ring 0 的顶级门禁卡。 - 如果是
11(也就是 3),说明当前代码手里只有 Ring 3 的普通门禁卡。
3. DPL (Descriptor Privilege Level):房间门上的“安全要求”
DPL 是目标内存段或者资源本身要求的权限级别。
内存里不是分了很多段嘛,每个段在全局描述符表(GDT)里都有一个对应的描述符(Descriptor)。这个描述符里面记录了这个段的各种信息,其中就包括 DPL。
- DPL 就像是贴在房间门上的安全等级要求。比如某个存放系统核心数据的内存段,它的 DPL 被设为了 0,意思就是“级别没到 0 的人禁止入内”。
它们是怎么互动的?(门禁核验)
这就到了查门禁的时候了。当你(当前的程序)想要去访问某一块内存,或者跨段跳转时,CPU 硬件在底层会自动把你的 CPL(你手里的卡)和目标位置的 DPL(门上的要求)拿来对比:
- 只有当你的 CPL 数值小于或等于 DPL 的数值时(数值越小权限越大,也就是你的特权得比门锁要求的高,或者一样高),CPU 才会放行。
- 如果一个 CPL 是 3 的普通程序,非要硬闯 DPL 是 0 的内核内存段,CPU 硬件立马就会翻脸,直接拦截并抛出一个异常(一般叫 General Protection Fault)。操作系统内核收到这个异常后,通常会无情地把这个不守规矩的程序给杀掉(这时候你可能就会看到程序崩溃退出了)。
简单来说,Ring 0 和 Ring 3 是等级划分的概念,而 CPL(在 %cs 里)和 DPL(在内存描述符里)是这套规则在硬件上的具体实现。
留下评论