驱动跑在哪、特权级、系统调用怎么陷入内核
syscall 指令 + 特权级切换。CPU 把你的程序分在两层跑:
| 态 | 特权级 | 能做什么 | 典型代码 |
|---|---|---|---|
| 用户态 | ring3(最低) | 只碰自己进程的内存、普通指令 | 你的 main()、STL、cout |
| 内核态 | ring0(最高) | 读写寄存器/端口/设备内存,管全部进程 | 系统调用处理、设备驱动 |
按顺序点按钮,看 read() 从用户态出发、陷入内核、再由驱动取数据、最后回来的完整旅程。右侧特权级指示灯会跟着变。
| 步 | 谁在做 | 发生什么 |
|---|---|---|
| 1 发请求 | 你的程序(用户态) | 调用 read(),C 库打包成 syscall |
| 2 切特权级 | CPU | 从 ring3 切到 ring0,跳到内核入口 |
| 3 处理+返回 | 内核 → 驱动 | 内核调驱动读写设备,最后 sysret 回用户态 |
系统调用 = 一次"用户态↔内核态"的过安检:要切特权级、查表、保存现场。量一下:普通函数调用约 1 ns,一次系统调用约 100~1000 ns(含上下文切换)——慢了 2~3 个数量级。
这就是为什么"每次循环里都 read() 一次"比"攒够 4 KB 一次 read()"慢几十上百倍——不是驱动慢,是来回安检的次数在花钱。类比:1 ns ≈ 光在空气里走 30 cm,1000 ns ≈ 光走 300 米——同一个量级的差距,肉眼根本看不见,但循环十万次就天差地别。
read() 时,CPU 发生了什么?