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() 會有三類資訊:

  1. device identifier:指出要控制哪個 device,通常是 file descriptor。
  2. command number:指出要 driver 執行哪個 operation。
  3. 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 大致會做:

  1. 透過 file descriptor 找到 open-file record。
  2. 從 open-file record 找到該 file/device 對應的 operation table。
  3. 如果是 device file,major number 決定要呼叫哪個 driver。
  4. Minor number 傳給 driver,讓 driver 找到具體 device instance。
  5. Driver 根據 command number 和 data pointer 執行 device-specific operation。

Trade-off

ioctl() 保留了硬體能力的彈性,但也降低了 portability。不同 OS、不同 driver 可能定義不同 command number 和 data structure,因此使用 ioctl() 的程式通常比只用標準 read/write 的程式更依賴特定平台或 driver。