linux驅動 ioctl介面

2021-08-08 23:48:26 字數 2926 閱讀 4064

核心中對底層裝置操作完全可以通過read、write介面來實現,在linux 2.2之前都是沒有ioctl介面的,2.4以後才引入ioctl介面。

典故(據說),以前在操作軟盤時,需要彈出光碟時命令為eject,可以通過write寫這個字串來傳輸這個指令,但是此時,如果要往軟盤中寫入」eject」字串時就出現了歧義的問題。雖然可以通過附加一些**繞過這個問題,但是不是嚴謹的開發者的習慣。所以出現了iotcl介面。

int (*ioctl) (struct inode *inode,struct file *filp,unsigned

int cmd,unsigned

long arg);

/*inode與filp兩個指標對應於應用程式傳遞的檔案描述符fd,這和傳遞open方法的引數一樣。

cmd 由使用者空間直接不經修改的傳遞給驅動程式

arg 可選。

*/

這個裡面主要的就是這個cmd,驅動開發人員定義好這個cmd,在介面內部就是根據cmd做的乙個分支處理。

在linux核心中是這樣定義乙個命令碼的:

序號:就是這個type中的序號,比如有些字元在核心中已經用了,但是對應的序號並沒有用完。自己定義時可以繼續跟著在後面定義。

方向:資料傳送的方向,如果這個特殊的命令涉及資料傳送. 可能的值是 _ioc_none(沒有資料傳輸), _ioc_read, _ioc_write, 和 _ioc_read|_ioc_write (資料在2個方向被傳送). 資料傳送是從應用程式的觀點來看待的; _ioc_read 意思是從裝置讀, 因此裝置必須寫到使用者空間. 注意這個成員是乙個位掩碼, 因此 _ioc_read 和 _ioc_write 可使用乙個邏輯 and 操作來抽取。

資料尺寸:就是傳輸資料的大小。

最終,這個命令其實就是乙個特殊的數字,在整個核心中保證和其他驅動所使用的命令不相同就行了。所以,可以自己隨便寫乙個特殊的數字。但是為了保持規範,就有了這個標準。

ioctl命令詳解

這裡常用的幾個

//nr為序號,datatype為資料型別,如int

_io(type, nr ) //沒有引數的命令

_ior(type, nr, datatype) //從驅動中讀資料

_iow(type, nr, datatype) //寫資料到驅動

_iowr(type,nr, datatype) //雙向傳送巨集

在ioctl函式實現中可以用以下一下兩個巨集函式來協助進行引數判斷

_ioc_type(cmd)用來判斷cmd的型別,就是跟定義的魔術進行比對,看是否屬於次裝置的ioctl的命令型別。

_ioc_nr(cmd)用來判斷命令的序號。防止出現定義的序號外的命令。

_ioc_dir(cmd)用來判斷命令的讀寫方向。

_ioc_size(cmd)用來判斷命令中引數的大小。

在具體實現中,用於傳輸資料的介面函式有四個,這幾個介面裡面都已經對引數的可讀寫操作性做了檢測,所以不用再呼叫access_ok來檢測了。

copy_from_user

copy_to_user

get_user

put_user

需要檢測的介面

__get_user

__put_user

檢測函式access_ok。

示例:

命令定義:

#define freg_ioctl_magic    'f'

#define freg_ioctl_s_index 0x20

#define freg_ioctl_num 2

/* 定義ioctl的命令 */

#define freg_ioctl_read _ior(freg_ioctl_magic, freg_ioctl_s_index, int)

#define freg_ioctl_write _iow(freg_ioctl_magic, freg_ioctl_s_index + 1, int)

驅動中ioctl介面實現:

static

long freg_ioctl(struct file* filp, unsigned int cmd, unsigned long val)

/* 檢測命令的有效性 */

if (_ioc_type(cmd) != freg_ioctl_magic)

if (_ioc_nr(cmd) < freg_ioctl_s_index || _ioc_nr(cmd) >= (freg_ioctl_s_index + freg_ioctl_num))

switch (cmd)

break;

case freg_ioctl_read:

printk(kern_info"ioctl_read.\r\n");

if (copy_to_user((void*)&val, &(dev->val), _ioc_size(cmd)))

break;

default:

ret = -einval;

break;

}out:

up(&(dev->sem));

return ret;

}

應用程式中使用:

fd = open("/dev/freg", o_rdwr);

ioctl(fd, freg_ioctl_read, &val);

linux驅動 ioctl函式解析

乙個字元裝置驅動會實現常規的開啟 關閉 讀 寫等功能,但是在一些細分的情景下,如果需要擴充套件新功能,通常以增設ioctl 命令的方式實現,其作用類似於 拾遺補漏 在檔案i o中,ioctl扮演著重要角色,本文將以驅動開發為側重點,從使用者空間到核心空間縱向分析ioctl函式。在man手冊中描述io...

linux驅動中的ioctl函式

我這裡說的ioctl函式是在驅動程式裡的,因為我不知道還有沒有別的場合用到了ioctl,所以就規定了我們討論的範圍。為什麼要寫篇文章呢,是因為我前一陣子被ioctl給搞混 了,這幾天才弄明白它,於是在這裡清理一下頭腦。一 什麼是ioctl。ioctl是裝置驅動程式中對裝置的i o通道進行管理的函式。...

linux如何通過ioctl呼叫驅動的

ioctl作用 應用層的ioctl函式傳入的cmd和arg引數會直接傳入驅動層的ioctl介面,在對應驅動檔案裡會對相應的命令進行操作 對於傳遞的ioctl命令有一定的規範,具體可以參考 include asm ioctl.h,documentation ioctl number.txt 這兩個檔案...