linux驅動程式開發中,ioctl命令編號問題,應該遵循include/asm/ioctl.h和Documentation/ioctl-number.txt這兩個檔案。一般命令使用四個欄位來組成32位的值來編碼:類型(幻數)、序數、傳送方向以及參數大小。Documentation/ioctl-number.txt已經羅列出了核心中使用的幻數,我們的驅動程式中應該避免與其衝突。
定義號碼的四個欄位如下所示:
type 幻數。選擇一個號碼,在整個程式中使用,該欄位佔8位。(_IOC_TYPEBITS)
number 序數。依次按順序增長,也佔8位。(_IOC_NRBITS)
direction。 資料的傳輸方向。這個方向是從使用者的角度來看的,_IOC_NONE(沒有資料轉送),_IOC_READ(從驅動讀出資料到使用者)、_IOC_WRITE(從使用者寫資料到驅動)以及_IOC_READ|_IOC_WRITE(雙向傳輸資料)。
size 所涉及的使用者資料的大小。與具體的體繫結構相關,通常佔13位或14位。_IOC_SIZEBITS定義其具體位元。
檔案中定義了一些常用的宏來構造命令編號。我們拿2.6.14版本來舉例。其中我們需要的有如下幾個宏定義,其他屬於從已定義的命令中解析各個欄位的值,我們暫不考慮。
/* 定義了每個欄位的長度:*/
#define _IOC_NRBITS 8
#define _IOC_TYPEBITS 8
#define _IOC_SIZEBITS 14
#define _IOC_DIRBITS 2
/*定義了每個欄位在32位整數中的位移量*/
#define _IOC_NRSHIFT 0
#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS)
#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS)
#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS)
/*定義了資料轉送方向,從使用者角度來看 */
#define _IOC_NONE 0U
#define _IOC_WRITE 1U
#define _IOC_READ 2U
/*根據四個欄位值產生一個命令編號,一般不直接使用*/
#define _IOC(dir,type,nr,size) /
(((dir) << _IOC_DIRSHIFT) | /
((type) << _IOC_TYPESHIFT) | /
((nr) << _IOC_NRSHIFT) | /
((size) << _IOC_SIZESHIFT))
/* 真正的根據類型、序號、方向和大小四個參數產生命令編號的宏,根據具體情況選擇以下四個之一*/
#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)) /*雙向傳輸資料*/
使用例子:
使用k作為幻數:
#define MY_MAGIC_DATA 'k'
#define MY_IOC_PRINT_DATA _IO(MY_MAGIC_DATA, 1)
#define MY_IOC_GET_DATA _IOR(MY_MAGIC_DATA, 2, int)
#define MY_IOC_SET_DATA _IOW(MY_MAGIC_DATA, 3, int)
#define MY_IOC_EXCHANGE_DATA _IOWR(MY_MAGIC_DATA,4,int)