ioctl 是裝置驅動程式中用於控制 I/O 裝置的關鍵系統呼叫。本文深入解析 Linux 核心中 ioctl 命令碼的位元結構、巨集定義、方向碼含義,並提供完整程式範例。
int ioctl(int handle, int cmd, ...);
| 欄位 | 巨集 | 寬度 | 位移 | 說明 |
|---|---|---|---|---|
| 序數 | _IOC_NRBITS | 8 bits | 0 | 命令序號 |
| 幻數 | _IOC_TYPEBITS | 8 bits | 8 | 裝置類型識別碼 |
| 大小 | _IOC_SIZEBITS | 14 bits | 16 | 資料結構大小 |
| 方向 | _IOC_DIRBITS | 2 bits | 30 | 資料流向 |
_IOC_NONE (0) — 無資料傳輸_IOC_WRITE (1) — 使用者空間 → 驅動程式(寫入裝置)_IOC_READ (2) — 驅動程式 → 使用者空間(從裝置讀取)// 無參數命令
#define _IO(type,nr) _IOC(_IOC_NONE, type, nr, 0)
// 讀取資料(驅動→用戶)
#define _IOR(type,nr,size) _IOC(_IOC_READ, type, nr, sizeof(size))
// 寫入資料(用戶→驅動)
#define _IOW(type,nr,size) _IOC(_IOC_WRITE, type, nr, sizeof(size))
// 雙向傳輸
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE, type, nr, sizeof(size))
#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)
#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)
#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
int main(void) {
int stat;
// 功能碼 8:檢查預設磁碟機是否可移除
stat = ioctl(0, 8, 0, 0);
if (!stat)
printf("Drive %c is removable.\n", getdisk() + 'A');
else
printf("Drive %c is not removable.\n", getdisk() + 'A');
return 0;
}
此範例展示如何直接使用 ioctl 進行底層裝置控制。