核心疑問
C 庫函數分為兩類:
- 需系統調用的(如 I/O、進程控制):`stdio.h`、`io.h` 中的函數最終調用內核提供的系統調用。
- 不需系統調用的(如數學運算、字符串處理):`math.h`、`string.h` 等純在用戶態執行。
問題:不調用系統調用的庫函數,硬件如何知道要執行什麼操作?ALU 如何理解庫函數的語義?系統調用與驅動程序的關係是什麼?
本質解釋
1. 用戶態指令與特權指令
CPU 指令分為 非特權指令(加減乘除、邏輯運算、數據移動等)和 特權指令(I/O 指令、修改頁表、中斷控制等)。
- 用戶態程序只能執行非特權指令。
- 特權指令只能在內核態執行,否則觸發異常(如 General Protection Fault)。
2. 純計算庫函數的執行流程
以 `strlen` 或 `sin` 為例:
- 編譯器將函數編譯為機器指令序列(非特權指令)。
- 程序調用時,CPU 直接取指、執行這些指令,操作寄存器、內存、ALU 完成計算。
- 無需進入內核,硬件「理解」的是指令編碼(如 `ADD`、`MUL`),而非高級語言語義。
3. 涉及硬件操作的庫函數
如 `printf`、`read`、`write`:
- 庫函數封裝參數,執行 系統調用指令(x86 上為 `int 0x80` 或 `syscall`)。
- CPU 切換到內核態,跳轉到系統調用處理程序。
- 內核驅動程序操作硬件控制器(如磁盤控制器、網卡),通過總線(I/O 端口、內存映射 I/O、DMA)完成數據傳輸。
- 返回用戶態,庫函數處理返回值/錯誤碼。
4. 系統調用與驅動程序的關係
- 系統調用:用戶態到內核態的受控入口,提供統一接口(如 `open`、`read`)。
- 驅動程序:內核中具體操作硬件的代碼,系統調用處理函數會調用驅動程序的相應操作(如 `file_operations->read`)。
- 系統調用是「接口」,驅動是「實現」;中間還有 VFS、文件系統層等抽象層。
總結
庫函數分兩類:純計算類直接用非特權指令在用戶態跑完;涉及硬件/資源類通過系統調用陷入內核,由驅動程序操作硬件。硬件只認機器指令,不認 C 語言。