Appearance
题目
下列选项中,会导致用户进程从用户态切换到内核态的操作是( )。
I. 整数除以零
II. sin() 函数调用
III. read 系统调用
错因
A
承认 Ⅰ 除零(异常 → 内核),却把 Ⅱ sin() 也算进去——但 sin() 是 C 标准库函数,纯计算(用泰勒展开 / CORDIC 算法),整个执行过程在用户态完成,没有任何机制需要进内核。把"调用"误以为是"系统调用"是一个常见混淆——库函数调用 ≠ 系统调用。
C
承认 Ⅱ Ⅲ 但漏了 Ⅰ——除零是算术异常,是内中断的一种,硬件层面立刻陷入内核态执行异常处理程序。漏掉它是没把"用户态切内核态"的三大触发途径(系统调用、异常、外部中断)想全。
D
把 Ⅰ Ⅱ Ⅲ 全选——掉进了 Ⅱ 的库函数陷阱。如果 sin() 用到了硬件浮点指令而硬件不支持还会触发非法指令异常陷入内核——但题目假设普通正常调用,sin() 只是软件算,不进内核。
总解析
用户态 → 内核态的三大触发路径:
| 路径 | 触发方式 | 例子 |
|---|---|---|
| 系统调用 | 用户主动陷入(trap / syscall 指令) | read、write、open、fork |
| 异常(内中断) | 指令执行过程中出错 | 除零、缺页、越界、非法指令 |
| 外部中断 | 异步信号(与当前指令无关) | 时钟中断、I/O 完成中断、键盘中断 |
逐项核对:
| 命题 | 类型 | 是否切换 |
|---|---|---|
| Ⅰ 整数除以零 | 算术异常 | ✓ 硬件触发,陷入内核处理 |
| Ⅱ sin() 函数调用 | C 标准库函数(用户态计算) | ✗ 全程用户态,不进内核 |
| Ⅲ read 系统调用 | 系统调用 | ✓ 主动陷入内核 |
关键区分:
- 库函数 vs 系统调用:库函数是用户态代码集合,sin() 是数学库实现,纯计算不涉及内核服务;read 是系统调用,必须进内核访问文件系统。
- 区分钥匙:这件事用户态能不能完成——能完成就不进内核(如算正弦值);必须用内核资源才能完成的(访问磁盘、分配进程、网络通信)才陷入。
正确的是 Ⅰ Ⅲ。
最终答案是 B。