Operating Systems Notes: The Path to the Kernel
Operating Systems Notes: The Path to the Kernel
1. 核心概念与关系
- Interrupt (中断): 异步事件,由外部硬件(键盘、网卡、定时器)触发。它的发生与程序执行流无关。
- 比喻: 外来的电话打断了你当前的工作。
 
 - Trap (陷阱): 同步事件,由内部软件(当前正在执行的指令)主动触发。它是可预测的,是程序逻辑的一部分。
- 比喻: 你在工作中遇到一个需要老板审批的环节,于是你主动放下工作去敲老板的门。
 
 - Exception (异常): 同步事件,由内部软件执行出错时被动触发。
- 比喻: 你在工作中算错了一个数字,导致流程无法继续,被动地需要老板介入。
 
 - System Call (系统调用): 一个高层概念,是操作系统提供给用户程序的服务接口(如读写文件、创建进程)。它不是一个硬件机制。
 
最重要的关系: 用户程序通过主动触发一次 Trap 来向内核发起一次 System Call 请求。 Trap 是实现 System Call 的底层机制。
2. int 指令的“身份”之谜
int指令是 Trap: 尽管它的名字叫int(interrupt),但它的行为(软件触发、同步发生)完全符合 Trap 的定义。- 为什么叫 
int: 因为它在硬件层面复用了与硬件中断相同的处理机制(中断描述符表 IDT)。 int的多样性:int 0x80: 在32位Linux上,是发起系统调用的传统方式。int 3: 用于调试断点。int 0: 用于处理除零异常。- 结论: 并非所有 
int触发的陷阱都是为了系统调用。 
3. 一次完整系统调用的生命周期
这是一个从用户空间到内核空间再返回的完整旅程:
- 用户空间 (User Space): 程序调用一个库函数,如 
write()。 - C 库包装 (Wrapper): 执行流进入C标准库(
glibc)。这个包装函数负责准备工作:- 将系统调用编号放入约定好的寄存器(如 
%rax)。 - 将函数参数放入其他寄存器。
 
 - 将系统调用编号放入约定好的寄存器(如 
 - 触发陷阱 (Trigger Trap): 包装函数执行一条特殊指令来陷入内核。
- 经典方式: 
int 0x80 - 现代方式: 
syscall 
 - 经典方式: 
 - 模式切换 (Mode Switch): CPU硬件响应陷阱指令,自动完成:
- 暂停用户程序。
 - 切换到内核模式 (Kernel Mode)。
 - 查找并跳转到内核的陷阱处理程序入口。
 
 - 内核空间 (Kernel Space):
- 内核的陷阱处理程序首先接管。
 - 它从 
%rax寄存器中读取系统调用编号。 - 使用该编号作为索引,在系统调用表 (System Call Table) 中查找并调用真正的内核函数(如 
sys_write())。 sys_write()执行特权操作。
 - 返回 (Return):
- 内核函数执行完毕,将返回值存入寄存器。
 - 内核执行 
sysret或iret指令,触发硬件切换回用户模式。 - 用户程序从陷阱指令之后的地方恢复执行。
 
 - 回到用户空间: C 库包装函数从寄存器中取回返回值,并将其返回给调用者。
 
4. syscall vs. int 0x80:效率的进化
- 共同点: 两者都是触发陷阱的指令,目的都是为了发起系统调用。进入内核后,确定具体调用的方式(查 
%rax寄存器)是一样的。 - 区别 (效率):
int 0x80: 走通用的中断处理路径,需要查询中断描述符表 (IDT),开销稍大。- 比喻: 去政府大楼的总咨询台问路,再被指引到正确的部门。
 
syscall: 走为系统调用优化的专用硬件路径,直接读取CPU专用寄存器 (MSR) 来找到入口地址,开销极小。- 比喻: 直接用专线电话打给目标部门的负责人,跳过了总咨询台。
 
 
结论: syscall 是一个更高效的“陷阱触发器”,但它并没有改变“陷阱 -> 查编号 -> 执行”这个基本流程。
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.
 Comments
GiscusUtterances