2013-04-04 188 views

回答

59

ioctl,這意味着「輸入輸出控制」是一種設備特定的系統調用。在Linux(300-400)中只有少數系統調用,它們不足以表達設備可能具有的所有獨特功能。因此,驅動程序可以定義允許用戶空間應用程序發送訂單的ioctl。然而,ioctl不是很靈活,並且往往會有點混亂(數十個「魔術數字」只能起作用或者不起作用),並且在將緩衝區傳遞到內核時也可能不安全 - 錯誤的處理可能會中斷事情很容易。

另一種是sysfs界面,在這裏建立了一個文件/sys/下,讀/寫,從和驅動器獲取信息。如何設置這個了一個例子:

static ssize_t mydrvr_version_show(struct device *dev, 
     struct device_attribute *attr, char *buf) 
{ 
    return sprintf(buf, "%s\n", DRIVER_RELEASE); 
} 

static DEVICE_ATTR(version, S_IRUGO, mydrvr_version_show, NULL); 

和驅動程序安裝過程中:

device_create_file(dev, &dev_attr_version); 

你將不得不爲你的設備中的文件/sys/,例如,/sys/block/myblk/version塊驅動程序。

另一種更重用的方法是netlink,它是一種通過BSD套接字接口與您的驅動程序通信的IPC(進程間通信)方法。例如,這由WiFi驅動程序使用。然後,您使用libnllibnl3庫從用戶空間與其通信。

+0

這個答案部分地回答了這個問題。 – 2016-11-29 03:44:00

100

ioctl功能在實現設備驅動程序以在設備上設置配置時非常有用。例如打印機具有配置選項來檢查和設置字體,字體大小等。ioctl可用於獲取當前字體以及將字體設置爲另一個字體。在用戶應用程序中,使用ioctl向打印機發送代碼,告訴其返回當前字體或將字體設置爲新字體。

int ioctl(int fd, int request, ...) 
  1. fd是文件描述符,由開啓
  2. request返回的一個是請求代碼。例如GETFONT將從打印機獲取當前字體,SETFONT將在打印機上設置字體。
  3. 第三個參數是void *。根據第二個論點,第三個可能會或可能不存在。 例如如果第二個參數是SETFONT,則第三個參數可能會將字體名稱設置爲ARIAL。

因此,現在int請求不僅僅是一個宏,還需要一個生成請求代碼,用於由用戶應用程序和設備驅動程序模塊使用,以確定設備上的哪個配置必須使用。一個用戶應用程序使用ioctl發送請求代碼,然後使用設備驅動程序模塊中的請求代碼確定要執行的操作。

的請求的代碼具有4個主要部分

1. A Magic number - 8 bits 
    2. A sequence number - 8 bits 
    3. Argument type (typically 14 bits), if any. 
    4. Direction of data transfer (2 bits). 

如果請求代碼是setfont程序設置在打印機上的字體,用於數據傳輸的方向是從用戶的應用程序的設備驅動程序模塊。用戶將字體名稱Arial發送到打印機。如果請求代碼是GETFONT,則方向是從打印機到用戶應用程序。

要生成請求碼的Linux提供一些預定義的函數等的宏。

1. _IO(MAGIC, SEQ_NO)兩者都是8位,0到255,例如讓我們說我們想暫停打印機。 這不需要ADATA轉移。所以,我們會生成請求代碼如下

#define PRIN_MAGIC 'P' 
    #define NUM 0 
    #define PAUSE_PRIN __IO(PRIN_MAGIC, NUM) 

現在使用的驅動模塊ioctl作爲

ret_val = ioctl(fd, PAUSE_PRIN); 

對應的系統調用將收到的代碼,並暫停打印機。

  • __IOW(MAGIC, SEQ_NO, TYPE)MAGICSEQ_NO同上,但第三部分對下一個參數的類型,回憶的ioctl第三個參數是void *。 W的__IOW指示數據的方向是從用戶應用到驅動模塊。讓我們舉個例子,假設 一個告訴打印機字體設置爲宋體。

    #define PRIN_MAGIC 'S' 
    #define SEQ_NO 1 
    #define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long) 
    
  • 進一步,

    char *font = "Arial"; 
        ret_val = ioctl(fd, SETFONT, font); 
    

    現在font是一個指針,這意味着它是最好的表示爲unsigned long的地址,因此的_IOW第三部分提到類型本身。此外,這個字體地址被傳遞給設備驅動模塊中實現的相應系統調用,如unsigned long,我們需要在使用它之前將其轉換爲適當的類型。內核空間可以訪問用戶空間,因此可以工作。像宏這樣的其他兩個函數分別是__IOR(MAGIC, SEQ_NO, TYPE)__IORW(MAGIC, SEQ_NO, TYPE),其中數據流的方向將分別從內核空間到用戶空間和兩個方向。

    請讓我知道,如果這有助於!

    +0

    我不知道上面的__IOW,__IOR和__IORW函數是否正確(在某些情況下,我的意思是雙下劃線,在某些情況下,我沒有使用雙下劃線)......感謝您的明確解釋! – jcoppens 2016-05-09 19:24:27