LDD3 高級(jí)字符驅(qū)動(dòng)程序操作

IOCTL

除了讀取和寫入設(shè)備之外炭序,大部分驅(qū)動(dòng)程序還需要另外一種能力,即通過(guò)設(shè)備驅(qū)動(dòng)程序執(zhí)行各種類型的硬件控制。簡(jiǎn)單的數(shù)據(jù)傳輸之外脖卖,大部分設(shè)備可以執(zhí)行其他一些操作袱吆,比如用戶空間經(jīng)常會(huì)要求設(shè)備鎖門、彈出介質(zhì)辜纲、報(bào)告錯(cuò)誤信息笨觅、改變波特率或者執(zhí)行自破壞拦耐,等等。這些操作通常通過(guò)ioctl方法支持见剩,該方法實(shí)現(xiàn)了同名的系統(tǒng)的調(diào)用揩魂。

用戶空間

int ioctl(int fd,unsigned long cmd,...);

這里用點(diǎn)只是為了在編譯時(shí)防止編譯器進(jìn)行類型檢查。第三個(gè)參數(shù)的具體形式依賴于要完成的控制命令炮温,也就是第二個(gè)參數(shù)火脉。有些控制命令不要參數(shù),有些需要一個(gè)整數(shù)參數(shù)柒啤,某些需要一個(gè)指針參數(shù)倦挂。使用指針可以向ioctl調(diào)用傳遞任意數(shù)據(jù),這樣設(shè)備可以與用戶空間交換任意數(shù)量的數(shù)據(jù)担巩。

本質(zhì)上說(shuō)每一個(gè)ioctl就是一個(gè)獨(dú)立地系統(tǒng)調(diào)用方援,而且是非公開的。有些需求需要我們通過(guò)其他途徑實(shí)現(xiàn)繁雜的控制操作涛癌,可能的方式包括:將命令嵌入到數(shù)據(jù)流中犯戏,或者使用虛擬文件系統(tǒng),比如sysfs或者設(shè)備相關(guān)的文件系統(tǒng)拳话。但是對(duì)于真正的設(shè)備操作來(lái)說(shuō)先匪,ioctl仍然是最簡(jiǎn)單且最有效的選擇。


驅(qū)動(dòng)程序的ioctl方法原型和用戶空間的版本存在有些不同:

int(*ioctl)(struct inode *inode,struct file *flip,unsigned int cmd,unsigned long arg);

inode和flip兩個(gè)指針的值對(duì)應(yīng)于應(yīng)用程序傳遞的文件描述符fd弃衍,這和傳給open方法的參數(shù)一樣呀非。參數(shù)cmd由用戶不經(jīng)修改地傳遞給驅(qū)動(dòng)程序,可選的arg參數(shù)則無(wú)論用戶使用的是指針還是整數(shù)值镜盯,都會(huì)以u(píng)nsigned long的形式傳遞給驅(qū)動(dòng)程序岸裙,如果用戶空間調(diào)用程序沒(méi)有傳遞第三個(gè)參數(shù),那么驅(qū)動(dòng)程序所接受的arg參數(shù)就處在未定義狀態(tài)速缆。由于對(duì)這個(gè)附加參數(shù)的類型檢查就被關(guān)閉了降允,所以如果為ioctl傳遞一個(gè)非法參數(shù),編譯器是無(wú)法報(bào)警的艺糜,這樣相關(guān)聯(lián)的程序錯(cuò)誤就很難被發(fā)現(xiàn)剧董。


ioctl實(shí)現(xiàn)都包括一個(gè)switch語(yǔ)句來(lái)根據(jù)cmd參數(shù)選擇對(duì)應(yīng)的操作。不同的命令被賦予不同的數(shù)值倦踢,為了簡(jiǎn)化代碼送滞,通常會(huì)在代碼中使用符號(hào)名代替數(shù)值,這些符號(hào)名由C的預(yù)處理語(yǔ)句定義辱挥。定制的設(shè)備驅(qū)動(dòng)程序通常會(huì)在它們的頭文件中聲明這些符號(hào)犁嗅,如scull中聲明了所使用的符號(hào)。為了訪問(wèn)這些符號(hào)晤碘,用戶程序自然也要包含這些頭文件褂微。


選擇ioctl命令

為了選擇對(duì)錯(cuò)誤的設(shè)備使用正確的命令功蜓,命令好應(yīng)該在系統(tǒng)范圍內(nèi)唯一。這種錯(cuò)誤匹配并不是不會(huì)發(fā)生宠蚂,程序可能發(fā)現(xiàn)自己正在試圖對(duì)FIFO和audio等非串行設(shè)備輸入流修改波特率式撼。如果每一個(gè)ioctl命令是唯一的,應(yīng)用程序進(jìn)行這種操作時(shí)就會(huì)得到一個(gè)EINVAL錯(cuò)誤求厕,而不是無(wú)意間成功的完成了意想不到的操作著隆。

要按照l(shuí)inux內(nèi)核的約定的方法為ioctl編號(hào),應(yīng)該首先看看include/asm/ioctl.h和Document/ioctl-number.txt這兩個(gè)文件呀癣。頭文件規(guī)定了要使用的位段:類型(幻數(shù))美浦、序數(shù)、傳送方向以及參數(shù)大小等等项栏。ioctl-number.txt文件中羅列了內(nèi)核所使用的幻數(shù)浦辨,這樣,在選擇自己的幻數(shù)時(shí)就可以避免和內(nèi)和沖突沼沈。這個(gè)文件也給出了為什么應(yīng)該使用這個(gè)約定的原因流酬。

以上來(lái)自LDD3


/*

* The original linux ioctl numbering scheme was just a general

* "anything goes" setup, where more or less random numbers were

* assigned.? Sorry, I was clueless when I started out on this.

*

* On the alpha, we'll try to clean it up a bit, using a more sane

* ioctl numbering, and also trying to be compatible with OSF/1 in

* the process. I'd like to clean it up for the i386 as well, but

* it's so painful recognizing both the new and the old numbers..

*/

最初linux ioctl命令號(hào)命令僅僅是一個(gè)通用的“怎么寫都行”的初始版本,使用了很多隨機(jī)的分配的數(shù)字列另。抱歉芽腾,我開始的時(shí)候毫無(wú)頭緒。

在alpha上访递,我們?cè)噲D清理一點(diǎn)晦嵌,使用更清楚點(diǎn)的ioctl的序列號(hào),并且也試圖努力和OSF/1在處理上兼容拷姿。我也愿意清理一下i386,但是同時(shí)識(shí)別老的和新的序列號(hào)實(shí)在是非常痛苦的。

#define _IOC_NRBITS 8

#define _IOC_TYPEBITS 8

#define _IOC_SIZEBITS 13

#define _IOC_DIRBITS 3

#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1)

#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1)

#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1)

#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1)

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

/*

* Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit.

* And this turns out useful to catch old ioctl numbers in header

* files for us.

*/

#define _IOC_NONE 1U

#define _IOC_READ 2U

#define _IOC_WRITE 4U

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

((unsigned int) \

(((dir)? << _IOC_DIRSHIFT) | \

((type) << _IOC_TYPESHIFT) | \

((nr)? << _IOC_NRSHIFT) | \

((size) << _IOC_SIZESHIFT)))

/* used to create numbers */

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

/* used to decode them.. */

#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)

#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)

#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)

#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)

/* ...and for the drivers/sound files... */

#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT)

#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT)

#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)

#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT)

#define IOCSIZE_SHIFT (_IOC_SIZESHIFT)

今天就先讀3頁(yè)書吧旱函,畢竟每天自己的時(shí)間也不是太多响巢,每天在公司做自己的事情,回到住處打開書看一會(huì)就已經(jīng)11點(diǎn)了棒妨,考慮明天把書帶到公司踪古。明天繼續(xù),come on券腔!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末伏穆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纷纫,更是在濱河造成了極大的恐慌枕扫,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辱魁,死亡現(xiàn)場(chǎng)離奇詭異烟瞧,居然都是意外死亡诗鸭,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門参滴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)强岸,“玉大人,你說(shuō)我怎么就攤上這事砾赔◎蚬浚” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵暴心,是天一觀的道長(zhǎng)妓盲。 經(jīng)常有香客問(wèn)我,道長(zhǎng)酷勺,這世上最難降的妖魔是什么本橙? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮脆诉,結(jié)果婚禮上甚亭,老公的妹妹穿的比我還像新娘。我一直安慰自己击胜,他們只是感情好亏狰,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著偶摔,像睡著了一般暇唾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辰斋,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天策州,我揣著相機(jī)與錄音,去河邊找鬼宫仗。 笑死够挂,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的藕夫。 我是一名探鬼主播孽糖,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼毅贮!你這毒婦竟也來(lái)了办悟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤滩褥,失蹤者是張志新(化名)和其女友劉穎病蛉,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铡恕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年琢感,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片探熔。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡驹针,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诀艰,到底是詐尸還是另有隱情柬甥,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布其垄,位于F島的核電站苛蒲,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏绿满。R本人自食惡果不足惜臂外,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望喇颁。 院中可真熱鬧漏健,春花似錦、人聲如沸橘霎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)姐叁。三九已至瓦盛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間外潜,已是汗流浹背原环。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留处窥,地道東北人扮念。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像碧库,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子巧勤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容