ioctl and Device Numbers
Why ioctl Exists
Application I/O interface 的主要目標是統一:disk、keyboard、network 等 device 都盡量透過少數標準 interface 使用。但如果介面太統一,就會失去 device 的特殊能力。
ioctl() 解決的是這個 tension:
- 標準 I/O system calls 負責 common behavior。
ioctl()負責 uncommon / device-specific control behavior。
這樣 OS 不需要為每個新硬體能力修改 system call table,但 application 仍然可以透過 driver 使用特殊功能。
ioctl Arguments
典型 ioctl() 會有三類資訊:
- device identifier:指出要控制哪個 device,通常是 file descriptor。
- command number:指出要 driver 執行哪個 operation。
- data pointer:指向 user memory 中的資料結構,用來傳入參數或接收結果。
Kernel 會根據 file descriptor 找到對應的 open-file record,再透過 dispatch table 呼叫該 device driver 的 ioctl routine。
Major and Minor Device Numbers
UNIX / Linux 中,device file 會對應到一組 major / minor numbers:
- Major number:指出 device type 或對應的 device driver。
- Minor number:指出同一 driver 管理下的哪一個 device instance。
例如多顆 disk 可能都由同一個 disk driver 管理,因此 major number 一樣;不同 partition 或 device instance 則用 minor number 區分。
How Request Finds Driver
當 application 對某個 device file 做 I/O 或 ioctl() 時,kernel 大致會做:
- 透過 file descriptor 找到 open-file record。
- 從 open-file record 找到該 file/device 對應的 operation table。
- 如果是 device file,major number 決定要呼叫哪個 driver。
- Minor number 傳給 driver,讓 driver 找到具體 device instance。
- Driver 根據 command number 和 data pointer 執行 device-specific operation。
Trade-off
ioctl() 保留了硬體能力的彈性,但也降低了 portability。不同 OS、不同 driver 可能定義不同 command number 和 data structure,因此使用 ioctl() 的程式通常比只用標準 read/write 的程式更依賴特定平台或 driver。