深入理解ioctl
《Linux設備驅動程序》ioctl詳解
除了讀取和寫入設備之外,大部分驅動程序還需要通過設備驅動程序實行各種類型的硬件控製。簡單的數據傳輸之外,大部分設備還可以執行其他一些操作,比如,用戶空間經常會請求設備鎖門,彈出介質,報告錯誤信息,改變波特率或者執行子破壞,等等。這些操作通常通過ioctl方法來支持。
ioctl在用戶空間的原型:
int ioctl(int fd, unsigned long cmd, ...)
這裏的...代表可變參數,他並不是代表任意數量的一組可變參數,通常,更具cmd來定,如果cmd不需要參數,那麼...就不會被使用,如果cmd需要參數,則就會使用...所以,它隻是代表一個可變參數。習慣上使用 char *argp來定義。這裏使用...就是為了編譯時防止編譯器進行類型檢查。
ioctl命令
每個驅動,都會有自己的ictol命令,那麼在不同的驅動,不同類型設備的驅動之間,這些命令必須唯一標示出來,例如,我們對非串口設備使用設置波特率的命令,如果按照通常意義上將,對ioctl命令從0或者1開始編號,假設1在串口驅動中代表設置波特率,由於其他原因,我們錯誤的在非串口設備中使用1的時候,可能並沒有發生錯誤,隻是進行了其他的操作而已,那麼這是在驅動程序中不允許的。但是如果ioctl命令編號是唯一的,那麼就不會出現這種無意間成功的完成了意想不到的操作。
為了方便程序員唯一的創建ioctl命令編號,內核中作了如下規定:
每一個命令號被分為多個字段。新的內核(2.6)中,定義號碼的新方法中使用4個字段來唯一標示一個命令。
<linux/ioctl.h>中對個字段的位數做出了定義
type
幻數。選擇一個號碼,並在整個驅動程序中使用這個號碼。
number
序數
direction
傳輸方向。_IOC_NONE(沒有數據傳輸),_IOC_READ,_IOC_WRITE以及_IOC_READ|_IOC_WRITE(雙向)這些方向。傳輸方向是站在應用程序的角度來看的。如果應用程序需要從驅動中讀取數據,則方向應該是_IOC_READ。
size
所涉及的用戶數據大小。對於大量數據傳輸可以忽略該字段。
以下是<linux/ioctl.h>中對各個字段所占的位數做出了說明
#define _IOC_NRBITS 8 //序數占8位
#define _IOC_TYPEBITS 8 //幻數占8位
/*
* Let any architecture override either of the following before
* including this file.
*/
#ifndef _IOC_SIZEBITS //size字段
# define _IOC_SIZEBITS 14
#endif
#ifndef _IOC_DIRBITS
# define _IOC_DIRBITS 2 //direction 字段
#endif
對於自己的驅動,如果需要使用特定的ioctl命令,則必須創建ioctl命令以及編號。內核中給出了創建ioctl命令的宏
/* used to create numbers */
#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0)
#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size)))
#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size))
#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size))
#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
版權申明:
轉載文章請注明原文出處https://blog.csdn.net/feiyinzilgd/archive/2010/03/03/5341173.aspx
並請聯係譚海燕本人或者前往譚海燕個人主頁留言
最後更新:2017-04-02 04:25:59