日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

“魔數(shù)"(也稱為"幻數(shù)")

 charlie_linux 2022-05-24 發(fā)布于廣東

一、魔數(shù)使用意義

        在驅(qū)動(dòng)程序里, ioctl() 函數(shù)上傳送的變量 cmd 是應(yīng)用程序用于區(qū)別設(shè)備驅(qū)動(dòng)程序請(qǐng)求處理內(nèi)容的值。cmd除了可區(qū)別數(shù)字外,還包含有助于處理的幾種相應(yīng)信息。 cmd的大小為 32位,共分 4 個(gè)域:bit31~bit30 2位為 “區(qū)別讀寫” 區(qū),作用是區(qū)分是讀取命令還是寫入命令。bit29~bit16 14位為 "數(shù)據(jù)大小" 區(qū),表示 ioctl() 中的 arg 變量傳送的內(nèi)存大小。bit15~bit08 8位為 “魔數(shù)"(也稱為"幻數(shù)")區(qū),這個(gè)值用以與其它設(shè)備驅(qū)動(dòng)程序的 ioctl 命令進(jìn)行區(qū)別。bit07~bit00 8位為 "基數(shù)"("命令序號(hào)")區(qū),是區(qū)分命令的命令順序序號(hào)。

二、linux內(nèi)核驅(qū)動(dòng)中_IO,_IOR,_IOW,_IOWR宏的用法與解析

     在驅(qū)動(dòng)程序里, ioctl() 函數(shù)上傳送的變量 cmd 是應(yīng)用程序用于區(qū)別設(shè)備驅(qū)動(dòng)程序請(qǐng)求處理內(nèi)容的值。cmd除了可區(qū)別數(shù)字外,還包含有助于處理的幾種相應(yīng)信息。 cmd的大小為 32位,共分 4 個(gè)域:

 bit31~bit30 2位為 “區(qū)別讀寫” 區(qū),作用是區(qū)分是讀取命令還是寫入命令。

bit29~bit15 14位為 "數(shù)據(jù)大小" 區(qū),表示 ioctl() 中的 arg 變量傳送的內(nèi)存大小。

bit20~bit08  8位為 “魔數(shù)"(也稱為"幻數(shù)")區(qū),這個(gè)值用以與其它設(shè)備驅(qū)動(dòng)程序的 ioctl 命令進(jìn)行區(qū)別。

bit07~bit00   8位為 "區(qū)別序號(hào)" 區(qū),是區(qū)分命令的命令順序序號(hào)。


像 命令碼中的 “區(qū)分讀寫區(qū)” 里的值可能是 _IOC_NONE (0值)表示無數(shù)據(jù)傳輸,_IOC_READ (讀), _IOC_WRI     TE   (寫) , _IOC_READ|_IOC_WRITE (雙向)。

內(nèi)核定義了 _IO() , _IOR() , IOW() 和 _IOWR() 這 4 個(gè)宏來輔助生成上面的 cmd 。下面分析 _IO() 的實(shí)現(xiàn),其它的類似:

在 asm-generic/ioctl.h 里可以看到 _IO() 的定義:

#define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0)

再看 _IOC() 的定義:

#define _IOC(dir,type,nr,size) \

(((dir)  << _IOC_DIRSHIFT) | \

((type) << _IOC_TYPESHIFT) | \

((nr)   << _IOC_NRSHIFT) | \

((size) << _IOC_SIZESHIFT))


可見,_IO() 的最后結(jié)果由 _IOC() 中的 4 個(gè)參數(shù)移位組合而成。

再看 _IOC_DI     RS   HIT 的定義:

#define _IOC_DIRSHIFT    (_IOC_SIZESHIFT+_IOC_SIZEBITS)

_IOC_SIZESHIFT 的定義:

#define _IOC_SIZESHIFT    (_IOC_TYPESHIFT+_IOC_TYPEBITS)

_IOC_TYPESHIF 的定義:

#define _IOC_TYPESHIFT    (_IOC_NRSHIFT+_IOC_NRBITS)

_IOC_NRSHIFT 的定義:

#define _IOC_NRSHIFT    0

_IOC_NRBITS 的定義:

#define _IOC_NRBITS    8

_IOC_TYPEBITS 的定義:

#define _IOC_TYPEBITS    8


由上面的定義,往上推得到:

引 用

_IOC_TYPESHIFT = 8

_IOC_SIZESHIFT = 16

_IOC_DIRSHIFT = 30

所以,(dir)  << _IOC_DIRSHIFT) 表是 dir 往左移 30 位,即移到 bit31~bit30 兩位上,得到方向(讀寫)的屬性;

(size) << _IOC_SIZESHIFT) 位左移 16 位得到“數(shù)據(jù)大小”區(qū);

(type) << _IOC_TYPESHIFT) 左 移 8位得到"魔數(shù)區(qū)" ;

(nr)   << _IOC_NRSHIFT)      左移 0 位( bit7~bit0) 。

這樣,就得到了 _IO() 的宏值。

這幾個(gè)宏的使用格式為:

_IO (魔數(shù), 基數(shù));

_IOR (魔數(shù), 基數(shù), 變量型)

_IOW  (魔數(shù), 基數(shù), 變量型)

_IOWR (魔數(shù), 基數(shù),變量型 )


魔數(shù) (magic number)

魔數(shù)范圍為 0~255 。通常,用英文     字符   "A" ~ "Z" 或者 "a" ~ "z" 來表示。設(shè)備驅(qū)動(dòng)程序從傳遞進(jìn)來的命令獲取魔數(shù),然后與自身處理的魔數(shù)想比較,如果相同則處理,不同則不處理。魔數(shù)是拒絕誤使用的初步輔助狀態(tài)。設(shè)備驅(qū)動(dòng) 程序可以通過 _IOC_TYPE (cmd) 來獲取魔數(shù)。不同的設(shè)備驅(qū)動(dòng)程序最好設(shè)置不同的魔數(shù),但并不是要求絕對(duì),也是可以使用其他設(shè)備驅(qū)動(dòng)程序已用過的魔數(shù)。

基(序列號(hào))數(shù)

基數(shù)用于區(qū)別各種命令。通常,從 0開始遞增,相同設(shè)備驅(qū)動(dòng)程序上可以重復(fù)使用該值。例如,讀取和寫入命令中使用了相同的基數(shù),設(shè)備驅(qū)動(dòng)程序也能分辨出來,原因在于設(shè)備驅(qū)動(dòng)程序區(qū)分命令時(shí) 使用 switch ,且直接使用命令變量 cmd值。創(chuàng)建命令的宏生成的值由多個(gè)域組合而成,所以即使是相同的基數(shù),也會(huì)判斷為不同的命令。設(shè)備驅(qū)動(dòng)程序想要從命令中獲取該基數(shù),就使用下面的宏:

_IOC_NR (cmd)

通常,switch 中的 case 值使用的是命令的本身。

變量型

變量型使用 arg 變量指定傳送的數(shù)據(jù)大小,但是不直接代入輸入,而是代入變量或者是變量的類型,原因是在使用宏創(chuàng)建命令,已經(jīng)包含了 sizeof() 編譯命令。比如 _IOR() 宏的定義是:

引用

#define _IOR(type,nr,size)    _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))

而 _IOC_TYPECHECK() 的定義正是:

引用

#define _IOC_TYPECHECK(t) (sizeof(t))

設(shè)備驅(qū)動(dòng)程序想要從傳送的命令獲取相應(yīng)的值,就要使用下列宏函數(shù):

_IOC_SIZE(cmd)

_IO 宏

該宏函數(shù)沒有可傳送的變量,只是用于傳送命令。例如如下約定:

引用

#define TEST_DRV_RESET _IO ('Q', 0)

此時(shí),省略由應(yīng)用程序傳送的 arg 變量或者代入 0 。在應(yīng)用程序中使用該宏時(shí),比如:

ioctl (dev, TEST_DEV_RESET, 0)   或者  ioctl (dev, TEST_DRV_RESET) 。

這是因?yàn)樽兞康挠行б蛩厥强勺円蛩?。只作為命令使用時(shí),沒有必要判 斷出設(shè)備上數(shù)據(jù)的輸出或輸入。因此,設(shè)備驅(qū)動(dòng)程序沒有必要執(zhí)行設(shè)備文件大開選項(xiàng)的相關(guān)處理。

_IOR 宏

該函數(shù)用 于創(chuàng)建從設(shè)備讀取數(shù)據(jù)的命令,例如可如下約定:

引用

#define TEST_DEV_READ  _IRQ('Q', 1, int)

這說明應(yīng)用程序從設(shè)備讀取數(shù)據(jù)的大小為 int 。下面宏用于判斷傳送到設(shè)備驅(qū)動(dòng)程序的 cmd 命令的讀寫狀態(tài):

_IOC_DIR (cmd)

運(yùn)行該宏時(shí),返回值的類型 如下:

_IOC_NONE                             :  無屬性

_IOC_READ                             :  可讀屬性

_IOC_WRITE                           : 可寫屬性

_IOC_READ | _IOC_WRITE : 可讀,可寫屬性

使用該命令時(shí),應(yīng)用程序的 ioctl() 的 arg 變量值指定設(shè)備驅(qū)動(dòng)程序上讀取數(shù)據(jù)時(shí)的緩存(結(jié)構(gòu)體)地址。

_IOW 宏

用于創(chuàng)建設(shè) 備上寫入數(shù)據(jù)的命令,其余內(nèi)容與 _IOR 相同。通常,使用該命令時(shí),ioctl() 的 arg 變量值指定設(shè)備驅(qū)動(dòng)程序上寫入數(shù)據(jù)時(shí)的緩存(結(jié)構(gòu)體)地址。

_IOWR 宏

用于創(chuàng)建設(shè)備上讀寫數(shù)據(jù)的命令。其余內(nèi) 容與 _IOR 相同。通常,使用該命令時(shí),ioctl() 的 arg 變量值指定設(shè)備驅(qū)動(dòng)程序上寫入或讀取數(shù)據(jù)時(shí)的緩存 (結(jié)構(gòu)體) 地址。

_IOR() , _IOW(), IORW() 的定義:

#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)))

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多