版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、 HYPERLINK 更多企業(yè)業(yè)學(xué)院:中小企企業(yè)管理理全能版版183套套講座+897700份份資料總經(jīng)理理、高層層管理49套講講座+1163888份資料中層管管理學(xué)院院46套講講座+660200份資料國(guó)學(xué)智智慧、易易經(jīng)46套講講座人力資資源學(xué)院院56套講講座+2271223份資料各階段段員工培培訓(xùn)學(xué)院院77套講講座+ 3244份資料員工管管理企業(yè)業(yè)學(xué)院67套講講座+ 87220份資料工廠生生產(chǎn)管理理學(xué)院52套講講座+ 139920份份資料財(cái)務(wù)管管理學(xué)院院53套講講座+ 179945份份資料銷(xiāo)售經(jīng)經(jīng)理學(xué)院院56套講講座+ 143350份份資料銷(xiāo)售人人員培訓(xùn)訓(xùn)學(xué)院72套講講座+ 48779份資料(
2、20008-009-228 116:228) 分類(lèi): 第 6 章 高高級(jí)字符符驅(qū)動(dòng)操操作在第 33 章, 我們們建立了了一個(gè)完完整的設(shè)設(shè)備驅(qū)動(dòng)動(dòng), 用用戶(hù)可用用來(lái)寫(xiě)入入和讀取取. 但但是一個(gè)個(gè)真正的的設(shè)備常常常提供供比同步步讀和寫(xiě)寫(xiě)更多的的功能. 現(xiàn)在在我們已已裝備有有調(diào)試工工具如果果發(fā)生錯(cuò)錯(cuò)誤, 并且一一個(gè)牢固固的并發(fā)發(fā)的理解解來(lái)幫助助避免事事情進(jìn)入入錯(cuò)誤- 我我們可安安全地前前進(jìn)并且且創(chuàng)建一一個(gè)更高高級(jí)的驅(qū)驅(qū)動(dòng).本章檢查查幾個(gè)你你需要理理解的概概念來(lái)編編寫(xiě)全特特性的字字符設(shè)備備驅(qū)動(dòng). 我們們從實(shí)現(xiàn)現(xiàn) iooctll 系統(tǒng)統(tǒng)調(diào)用開(kāi)開(kāi)始, 它是用用作設(shè)備備控制的的普通接接口. 接著我我們進(jìn)入入
3、各種和和用戶(hù)空空間同步步的方法法; 在在本章結(jié)結(jié)尾, 你有一一個(gè)充分分的認(rèn)識(shí)識(shí)對(duì)于如如何使進(jìn)進(jìn)程睡眠眠(并且且喚醒它它們), 實(shí)現(xiàn)現(xiàn)非阻塞塞的 II/O, 并且且通知用用戶(hù)空間間當(dāng)你的的設(shè)備可可用來(lái)讀讀或?qū)? 我們們以查看看如何在在驅(qū)動(dòng)中中實(shí)現(xiàn)幾幾個(gè)不同同的設(shè)備備存取策策略來(lái)結(jié)結(jié)束.這里討論論的概念念通過(guò) scuull 驅(qū)動(dòng)的的幾個(gè)修修改版本本來(lái)演示示. 再再一次, 所有有的都使使用內(nèi)存存中的虛虛擬設(shè)備備來(lái)實(shí)現(xiàn)現(xiàn), 因因此你可可自己試試驗(yàn)這些些代碼而而不必使使用任何何特別的的硬件. 到此此為止, 你可可能在想想親手使使用真正正的硬件件, 但但是那將將必須等等到第 9 章章.6.1.iocctl
4、 接口大部分驅(qū)驅(qū)動(dòng)需要要 - 除了了讀寫(xiě)設(shè)設(shè)備的能能力 - 通通過(guò)設(shè)備備驅(qū)動(dòng)進(jìn)進(jìn)行各種種硬件控控制的能能力. 大部分分設(shè)備可可進(jìn)行超超出簡(jiǎn)單單的數(shù)據(jù)據(jù)傳輸之之外的操操作; 用戶(hù)空空間必須須常常能能夠請(qǐng)求求, 例例如, 設(shè)備鎖鎖上它的的門(mén), 彈出它它的介質(zhì)質(zhì), 報(bào)報(bào)告錯(cuò)誤誤信息, 改變變波特率率, 或或者自我我銷(xiāo)毀. 這些些操作常常常通過(guò)過(guò) iooctll 方法法來(lái)支持持, 它它通過(guò)相相同名子子的系統(tǒng)統(tǒng)調(diào)用來(lái)來(lái)實(shí)現(xiàn).在用戶(hù)空空間, iocctl 系統(tǒng)調(diào)調(diào)用有下下面的原原型:int iocctl(intt fdd, uunsiigneed llongg cmmd, .); 這個(gè)原型型由于這這些點(diǎn)而
5、而凸現(xiàn)于于 Unnix 系統(tǒng)調(diào)調(diào)用列表表, 這這些點(diǎn)常常常表示示函數(shù)有有數(shù)目不不定的參參數(shù). 在實(shí)際際系統(tǒng)中中, 但但是, 一個(gè)系系統(tǒng)調(diào)用用不能真真正有變變數(shù)目的的參數(shù). 系統(tǒng)統(tǒng)調(diào)用必必須有一一個(gè)很好好定義的的原型, 因?yàn)闉橛脩?hù)程程序可存存取它們們只能通通過(guò)硬件件的門(mén)門(mén). 因此, 原型型中的點(diǎn)點(diǎn)不表示示一個(gè)變變數(shù)目的的參數(shù), 而是是一個(gè)單單個(gè)可選選的參數(shù)數(shù), 傳傳統(tǒng)上標(biāo)標(biāo)識(shí)為 chaar *arggp. 這些點(diǎn)點(diǎn)在那里里只是為為了阻止止在編譯譯時(shí)的類(lèi)類(lèi)型檢查查. 第第 3 個(gè)參數(shù)數(shù)的實(shí)際際特點(diǎn)依依賴(lài)所發(fā)發(fā)出的特特定的控控制命令令( 第第 2 個(gè)參數(shù)數(shù) ). 一些些命令不不用參數(shù)數(shù), 一一些用一
6、一個(gè)整數(shù)數(shù)值, 以及一一些使用用指向其其他數(shù)據(jù)據(jù)的指針針. 使使用一個(gè)個(gè)指針是是傳遞任任意數(shù)據(jù)據(jù)到 iiocttl 調(diào)調(diào)用的方方法; 設(shè)備接接著可與與用戶(hù)空空間交換換任何數(shù)數(shù)量的數(shù)數(shù)據(jù).iocttl 調(diào)調(diào)用的非非結(jié)構(gòu)化化特性使使它在內(nèi)內(nèi)核開(kāi)發(fā)發(fā)者中失失寵. 每個(gè) iocctl 命令, 基本本上, 是一個(gè)個(gè)單獨(dú)的的, 常常常無(wú)文文檔的系系統(tǒng)調(diào)用用, 并并且沒(méi)有有方法以以任何類(lèi)類(lèi)型的全全面的方方式核查查這些調(diào)調(diào)用. 也難于于使非結(jié)結(jié)構(gòu)化的的 iooctll 參數(shù)數(shù)在所有有系統(tǒng)上上一致工工作; 例如, 考慮慮運(yùn)行在在 322-位模模式的一一個(gè)用戶(hù)戶(hù)進(jìn)程的的 644-位 系統(tǒng). 結(jié)果果, 有有很大的的
7、壓力來(lái)來(lái)實(shí)現(xiàn)混混雜的控控制操作作, 只只通過(guò)任任何其他他的方法法. 可可能的選選擇包括括嵌入命命令到數(shù)數(shù)據(jù)流(本章稍稍后我們們將討論論這個(gè)方方法)或或者使用用虛擬文文件系統(tǒng)統(tǒng), 要要么是 syssfs 要么是是設(shè)備特特定的文文件系統(tǒng)統(tǒng). (我們將將在 114 章章看看 syssfs). 但但是, 事實(shí)是是 iooctll 常常常是最容容易的和和最直接接的選擇擇,對(duì)于于真正的的設(shè)備操操作.iocttl 驅(qū)驅(qū)動(dòng)方法法有和用用戶(hù)空間間版本不不同的原原型:int (*iiocttl) (sttrucct iinodde *inoode, sttrucct ffilee *ffilpp, uunsiig
8、need iint cmdd, uunsiigneed llongg arrg);inodde 和和 fiilp 指針是是對(duì)應(yīng)應(yīng)應(yīng)用程序序傳遞的的文件描描述符 fd 的值, 和傳傳遞給 opeen 方方法的相相同參數(shù)數(shù). ccmd 參數(shù)從從用戶(hù)那那里不改改變地傳傳下來(lái), 并且且可選的的參數(shù) argg 參數(shù)數(shù)以一個(gè)個(gè) unnsiggnedd loong 的形式式傳遞, 不管管它是否否由用戶(hù)戶(hù)給定為為一個(gè)整整數(shù)或一一個(gè)指針針. 如如果調(diào)用用程序不不傳遞第第 3 個(gè)參數(shù)數(shù), 被被驅(qū)動(dòng)操操作收到到的 aarg 值是無(wú)無(wú)定義的的. 因因?yàn)轭?lèi)型型檢查在在這個(gè)額額外參數(shù)數(shù)上被關(guān)關(guān)閉, 編譯器器不能警警告你如
9、如果一個(gè)個(gè)無(wú)效的的參數(shù)被被傳遞給給 iooctll, 并并且任何何關(guān)聯(lián)的的錯(cuò)誤將將難以查查找.如果你可可能想到到的, 大部分分 iooctll 實(shí)現(xiàn)現(xiàn)包括一一個(gè)大的的 swwitcch 語(yǔ)語(yǔ)句來(lái)根根據(jù) ccmd 參數(shù), 選擇擇正確的的做法. 不同同的命令令有不同同的數(shù)值值, 它它們常常常被給予予符號(hào)名名來(lái)簡(jiǎn)化化編碼. 符號(hào)號(hào)名通過(guò)過(guò)一個(gè)預(yù)預(yù)處理定定義來(lái)安安排. 定制的的驅(qū)動(dòng)常常常聲明明這樣的的符號(hào)在在它們的的頭文件件中; scuull.h 為為 scculll 聲明明它們. 用戶(hù)戶(hù)程序必必須, 當(dāng)然, 包含含那個(gè)頭頭文件來(lái)來(lái)存取這這些符號(hào)號(hào).6.1.1.選擇 iocctl 命令在為 iioct
10、tl 編編寫(xiě)代碼碼之前, 你需需要選擇擇對(duì)應(yīng)命命令的數(shù)數(shù)字. 許多程程序員的的第一個(gè)個(gè)本能的的反應(yīng)是是選擇一一組小數(shù)數(shù)從0或或1開(kāi)始始, 并并且從此此開(kāi)始向向上. 但是, 有充充分的理理由不這這樣做. iooctll 命令令數(shù)字應(yīng)應(yīng)當(dāng)在這這個(gè)系統(tǒng)統(tǒng)是唯一一的, 為了阻阻止向錯(cuò)錯(cuò)誤的設(shè)設(shè)備發(fā)出出正確的的命令而而引起的的錯(cuò)誤. 這樣樣的不匹匹配不會(huì)會(huì)不可能能發(fā)生, 并且且一個(gè)程程序可能能發(fā)現(xiàn)它它自己試試圖改變變一個(gè)非非串口輸輸入系統(tǒng)統(tǒng)的波特特率, 例如一一個(gè) FFIFOO 或者者一個(gè)音音頻設(shè)備備. 如如果這樣樣的 iiocttl 號(hào)號(hào)是唯一一的, 這個(gè)應(yīng)應(yīng)用程序序得到一一個(gè) EEINVVAL 錯(cuò)誤
11、而而不是繼繼續(xù)做不不應(yīng)當(dāng)做做的事情情.為幫助程程序員創(chuàng)創(chuàng)建唯一一的 iiocttl 命命令代碼碼, 這這些編碼碼已被劃劃分為幾幾個(gè)位段段. LLinuux 的的第一個(gè)個(gè)版本使使用 116-位位數(shù): 高 88 位是是關(guān)聯(lián)這這個(gè)設(shè)備備的魔魔數(shù), 低 8 位位是一個(gè)個(gè)順序號(hào)號(hào), 在在設(shè)備內(nèi)內(nèi)唯一. 這樣樣做是因因?yàn)?LLinuus 是是無(wú)能能的(他自己己的話); 一一個(gè)更好好的位段段劃分僅僅在后來(lái)來(lái)被設(shè)想想. 不不幸的是是, 許許多驅(qū)動(dòng)動(dòng)仍然使使用老傳傳統(tǒng). 它們不不得不: 改變變命令編編碼會(huì)破破壞大量量的二進(jìn)進(jìn)制程序序,并且且這不是是內(nèi)核開(kāi)開(kāi)發(fā)者愿愿意見(jiàn)到到的.根據(jù) LLinuux 內(nèi)內(nèi)核慣例例來(lái)
12、為你你的驅(qū)動(dòng)動(dòng)選擇 iocctl 號(hào), 你應(yīng)當(dāng)當(dāng)首先檢檢查 iinclludee/assm/iiocttl.hh 和 Doccumeentaatioon/iiocttl-nnumbber.txtt. 這這個(gè)頭文文件定義義你將使使用的位位段: typpe(魔魔數(shù)), 序號(hào)號(hào), 傳傳輸方向向, 和和參數(shù)大大小. iocctl-nummberr.txxt 文文件列舉舉了在內(nèi)內(nèi)核中使使用的魔魔數(shù), 因因此你將將可選擇擇你自己己的魔數(shù)數(shù)并且避避免交疊疊. 這這個(gè)文本本文件也也列舉了了為什么么應(yīng)當(dāng)使使用慣例例的原因因.定義 iiocttl 命命令號(hào)的的正確方方法使用用 4 個(gè)位段段, 它它們有下下列的含含
13、義. 這個(gè)列列表中介介紹的新新符號(hào)定定義在 .typee 魔數(shù). 只是選選擇一個(gè)個(gè)數(shù)(在在參考了了 iooctll-nuumbeer.ttxt之之后)并并且使用用它在整整個(gè)驅(qū)動(dòng)動(dòng)中. 這個(gè)成成員是 8 位位寬(_IOCC_TYYPEBBITSS). numbber 序(順序序)號(hào). 它是是 8 位(_IOCC_NRRBITTS)寬寬. direectiion 數(shù)據(jù)傳送送的方向向,如果果這個(gè)特特殊的命命令涉及及數(shù)據(jù)傳傳送. 可能的的值是 _IOOC_NNONEE(沒(méi)有有數(shù)據(jù)傳傳輸), _IIOC_REAAD, _IOOC_WWRITTE, 和 _IOCC_REEAD|_IOOC_WWRITTE
14、(數(shù)據(jù)在在2個(gè)方方向被傳傳送). 數(shù)據(jù)據(jù)傳送是是從應(yīng)用用程序的的觀點(diǎn)來(lái)來(lái)看待的的; _IOCC_REEAD 意思是是從設(shè)備備讀, 因此設(shè)設(shè)備必須須寫(xiě)到用用戶(hù)空間間. 注注意這個(gè)個(gè)成員是是一個(gè)位位掩碼, 因此此 _IIOC_REAAD 和和 _IIOC_WRIITE 可使用用一個(gè)邏邏輯 AAND 操作來(lái)來(lái)抽取.sizee 涉及到的的用戶(hù)數(shù)數(shù)據(jù)的大大小. 這個(gè)成成員的寬寬度是依依賴(lài)體系系的, 但是常常常是 13 或者 14 位. 你可為為你的特特定體系系在宏 _IOOC_SSIZEEBITTS 中中找到它它的值. 你使使用這個(gè)個(gè) siize 成員不不是強(qiáng)制制的 - 內(nèi)核核不檢查查它 - 但但是它是
15、是一個(gè)好好主意. 正確確使用這這個(gè)成員員可幫助助檢測(cè)用用戶(hù)空間間程序的的錯(cuò)誤并并使你實(shí)實(shí)現(xiàn)向后后兼容, 如果果你曾需需要改變變相關(guān)數(shù)數(shù)據(jù)項(xiàng)的的大小. 如果果你需要要更大的的數(shù)據(jù)結(jié)結(jié)構(gòu), 但是, 你可可忽略這這個(gè) ssizee 成員員. 我我們很快快見(jiàn)到如如何使用用這個(gè)成成員.頭文件 , 它包含含在 中, 定義宏宏來(lái)幫助助建立命命令號(hào), 如下下: _IO(typpe,nnr)(給沒(méi)有有參數(shù)的的命令), _IORR(tyype, nrre, dattatyype)(給從從驅(qū)動(dòng)中中讀數(shù)據(jù)據(jù)的), _IIOW(typpe,nnr,ddataatyppe)(給寫(xiě)數(shù)數(shù)據(jù)), 和 _IOOWR(typpe,
16、nnr,ddataatyppe)(給雙向向傳送). ttypee 和 nummberr 成員員作為參參數(shù)被傳傳遞, 并且 sizze 成成員通過(guò)過(guò)應(yīng)用 sizzeoff 到 dattatyype 參數(shù)而而得到.這個(gè)頭文文件還定定義宏, 可被被用在你你的驅(qū)動(dòng)動(dòng)中來(lái)解解碼這個(gè)個(gè)號(hào): _IOOC_DDIR(nr), _IOCC_TYYPE(nr), _IOCC_NRR(nrr), 和 _IOCC_SIIZE(nr). 我我們不進(jìn)進(jìn)入任何何這些宏宏的細(xì)節(jié)節(jié), 因因?yàn)轭^文文件是清清楚的, 并且且在本節(jié)節(jié)稍后有有例子代代碼展示示.這里是一一些 iiocttl 命命令如何何在 ssculll 被被定義的的.
17、 特特別地, 這些些命令設(shè)設(shè)置和獲獲得驅(qū)動(dòng)動(dòng)的可配配置參數(shù)數(shù)./* UUse k ass maagicc nuumbeer */#deffinee SCCULLL_IOOC_MMAGIIC k/* PPleaase usee a diffferrentt 8-bitt nuumbeer iin yyourr coode */#deffinee SCCULLL_IOOCREESETT _IIO(SSCULLL_IIOC_MAGGIC, 0)/* * SS meeanss SSet thhrouugh a pptr, * TT meeanss TTelll ddireectlly wwithh t
18、hhe aarguumennt vvaluue * GG meeanss GGet: rreplly bby ssetttingg thhrouugh a ppoinnterr * QQ meeanss QQuerry: reespoonsee iss onn thhe rretuurn vallue * XX meeanss eeXchhangge: swwitcch GG annd SS attomiicallly * HH meeanss ssHifft: swwitcch TT annd QQ attomiicallly */#deffinee SCCULLL_IOOCSQQUANNT
19、UMM _IIOW(SCUULL_IOCC_MAAGICC, 11, iint)#deffinee SCCULLL_IOOCSQQSETT _IIOW(SCUULL_IOCC_MAAGICC, 22, iint)#deffinee SCCULLL_IOOCTQQUANNTUMM _IIO(SSCULLL_IIOC_MAGGIC, 3)#deffinee SCCULLL_IOOCTQQSETT _IIO(SSCULLL_IIOC_MAGGIC, 4)#deffinee SCCULLL_IOOCGQQUANNTUMM _IIOR(SCUULL_IOCC_MAAGICC, 55, iint)#def
20、finee SCCULLL_IOOCGQQSETT _IIOR(SCUULL_IOCC_MAAGICC, 66, iint)#deffinee SCCULLL_IOOCQQQUANNTUMM _IIO(SSCULLL_IIOC_MAGGIC, 7)#deffinee SCCULLL_IOOCQQQSETT _IIO(SSCULLL_IIOC_MAGGIC, 8)#deffinee SCCULLL_IOOCXQQUANNTUMM _IIOWRR(SCCULLL_IOOC_MMAGIIC, 9, intt)#deffinee SCCULLL_IOOCXQQSETT _IIOWRR(SCCULLL_
21、IOOC_MMAGIIC,110, intt)#deffinee SCCULLL_IOOCHQQUANNTUMM _IIO(SSCULLL_IIOC_MAGGIC, 111)#deffinee SCCULLL_IOOCHQQSETT _IIO(SSCULLL_IIOC_MAGGIC, 122)#deffinee SCCULLL_IOOC_MMAXNNR 114真正的源源文件定定義幾個(gè)個(gè)額外的的這里沒(méi)沒(méi)有出現(xiàn)現(xiàn)的命令令.我們選擇擇實(shí)現(xiàn) 2 種種方法傳傳遞整數(shù)數(shù)參數(shù): 通過(guò)過(guò)指針和和通過(guò)明明確的值值(盡管管, 由由于一個(gè)個(gè)已存在在的慣例例, iiocllt 應(yīng)應(yīng)當(dāng)通過(guò)過(guò)指針交交換值). 類(lèi)類(lèi)似地,
22、 2 種方法法被用來(lái)來(lái)返回一一個(gè)整數(shù)數(shù)值:通通過(guò)指針針和通過(guò)過(guò)設(shè)置返返回值. 這個(gè)個(gè)有效只只要返回回值是一一個(gè)正的的整數(shù); 如同同你現(xiàn)在在所知道道的, 在從任任何系統(tǒng)統(tǒng)調(diào)用返返回時(shí), 一個(gè)個(gè)正值被被保留(如同我我們?cè)?reaad 和和 wrritee 中見(jiàn)見(jiàn)到的), 而而一個(gè)負(fù)負(fù)值被看看作一個(gè)個(gè)錯(cuò)誤并并且被用用來(lái)在用用戶(hù)空間間設(shè)置 errrno.excchannge和sshifft操操作對(duì)于于 scculll 沒(méi)有有特別的的用處. 我們們實(shí)現(xiàn)excchannge來(lái)顯示示驅(qū)動(dòng)如如何結(jié)合合獨(dú)立的的操作到到單個(gè)的的原子的的操作, 并且且shhiftt來(lái)連連接ttelll和queery. 有有時(shí)需要要
23、象這樣樣的原子子的測(cè)試試-和-設(shè)置操操作, 特別地地, 當(dāng)當(dāng)應(yīng)用程程序需要要設(shè)置和和釋放鎖鎖.命令的明明確的序序號(hào)沒(méi)有有特別的的含義. 它只只用來(lái)區(qū)區(qū)分命令令. 實(shí)實(shí)際上, 你甚甚至可使使用相同同的序號(hào)號(hào)給一個(gè)個(gè)讀命令令和一個(gè)個(gè)寫(xiě)命令令, 因因?yàn)閷?shí)際際的 iiocttl 號(hào)號(hào)在方方向位位是不同同的, 但是你你沒(méi)有理理由這樣樣做. 我們選選擇在任任何地方方不使用用命令的的序號(hào)除除了聲明明中, 因此我我們不分分配一個(gè)個(gè)返回值值給它. 這就就是為什什么明確確的號(hào)出出現(xiàn)在之之前給定定的定義義中. 這個(gè)例例子展示示了一個(gè)個(gè)使用命命令號(hào)的的方法, 但是是你有自自由不這這樣做.除了少數(shù)數(shù)幾個(gè)預(yù)預(yù)定義的的命令
24、(馬上就就討論), iiocttl 的的 cmmd 參參數(shù)的值值當(dāng)前不不被內(nèi)核核使用, 并且且在將來(lái)來(lái)也很不不可能. 因此此, 你你可以, 如果果你覺(jué)得得懶, 避免前前面展示示的復(fù)雜雜的聲明明并明確確聲明一一組調(diào)整整數(shù)字. 另一一方面, 如果果你做了了, 你你不會(huì)從從使用這這些位段段中獲益益, 并并且你會(huì)會(huì)遇到困困難如果果你曾提提交你的的代碼來(lái)來(lái)包含在在主線內(nèi)內(nèi)核中. 頭文文件 是是這個(gè)老老式方法法的例子子, 使使用 116-位位的調(diào)整整值來(lái)定定義 iiocttl 命命令. 那個(gè)源源代碼依依靠調(diào)整整數(shù)因?yàn)闉槭褂媚悄莻€(gè)時(shí)候候遵循的的慣例, 不是是由于懶懶惰. 現(xiàn)在改改變它可可能導(dǎo)致致無(wú)理由由的不
25、兼兼容.6.1.2.返回值值iocttl 的的實(shí)現(xiàn)常常常是一一個(gè) sswittch 語(yǔ)句, 基于于命令號(hào)號(hào). 但但是當(dāng)命命令號(hào)沒(méi)沒(méi)有匹配配一個(gè)有有效的操操作時(shí)缺缺省的選選擇應(yīng)當(dāng)當(dāng)是什么么? 這這個(gè)問(wèn)題題是有爭(zhēng)爭(zhēng)議的. 幾個(gè)個(gè)內(nèi)核函函數(shù)返回回 -EENIVVAL(Innvallid arggumeent), 它有意意義是因因?yàn)槊盍顓?shù)確確實(shí)不是是一個(gè)有有效的. POOSIXX 標(biāo)準(zhǔn)準(zhǔn), 但但是, 說(shuō)如果果一個(gè)不不合適的的 iooctll 命令令被發(fā)出出, 那那么 -ENOOTTYY 應(yīng)當(dāng)當(dāng)被返回回. 這這個(gè)錯(cuò)誤誤碼被 C 庫(kù)庫(kù)解釋為為設(shè)備備的不適適當(dāng)?shù)?iocctl, 這這常常正正是程序序員需
26、要要聽(tīng)到的的. 然然而, 它仍然然是相當(dāng)當(dāng)普遍的的來(lái)返回回 -EEINVVAL, 對(duì)于于響應(yīng)一一個(gè)無(wú)效效的 iiocttl 命命令.6.1.3.預(yù)定義義的命令令盡管 iiocttl 系系統(tǒng)調(diào)用用最常用用來(lái)作用用于設(shè)備備, 內(nèi)內(nèi)核能識(shí)識(shí)別幾個(gè)個(gè)命令. 注意意這些命命令, 當(dāng)用到到你的設(shè)設(shè)備時(shí), 在你你自己的的文件操操作被調(diào)調(diào)用之前前被解碼碼. 因因此, 如果你你選擇相相同的號(hào)號(hào)給一個(gè)個(gè)你的 iocctl命命令, 你不會(huì)會(huì)看到任任何的給給那個(gè)命命令的請(qǐng)請(qǐng)求, 并且應(yīng)應(yīng)用程序序獲得某某些不期期望的東東西, 因?yàn)樵谠?iooctll 號(hào)之之間的沖沖突.預(yù)定義命命令分為為 3 類(lèi):可對(duì)任何何文件發(fā)發(fā)出的
27、(常規(guī), 設(shè)備備, FFIFOO, 或或者 ssockket) 的那那些.只對(duì)常規(guī)規(guī)文件發(fā)發(fā)出的那那些.對(duì)文件系系統(tǒng)類(lèi)型型特殊的的那些.最后一類(lèi)類(lèi)的命令令由宿主主文件系系統(tǒng)的實(shí)實(shí)現(xiàn)來(lái)執(zhí)執(zhí)行(這這是 cchatttr 命令如如何工作作的). 設(shè)備備驅(qū)動(dòng)編編寫(xiě)者只只對(duì)第一一類(lèi)命令令感興趣趣, 它它們的魔魔數(shù)是 T. 查查看其他他類(lèi)的工工作留給給讀者作作為練習(xí)習(xí); eext22_iooctll 是最最有趣的的函數(shù)(并且比比預(yù)期的的要容易易理解), 因因?yàn)樗鼘?shí)實(shí)現(xiàn) aappeend-onlly 標(biāo)標(biāo)志和 immmutaablee 標(biāo)志志.下列 iiocttl 命命令是預(yù)預(yù)定義給給任何文文件, 包括設(shè)設(shè)
28、備特殊殊的文件件:FIOCCLEXX 設(shè)置 cclosse-oon-eexecc 標(biāo)志志( CClosse oon EEXecc). 設(shè)置這這個(gè)標(biāo)志志使文件件描述符符被關(guān)閉閉, 當(dāng)當(dāng)調(diào)用進(jìn)進(jìn)程執(zhí)行行一個(gè)新新程序時(shí)時(shí).FIONNCLEEX 清除 cclosse-nno-eexecc 標(biāo)志志( NNot CLoose on EXeec). 這個(gè)個(gè)命令恢恢復(fù)普通通文件行行為, 復(fù)原上上面 FFIOCCLEXX 所做做的. FIOOASYYNC 為這個(gè)個(gè)文件設(shè)設(shè)置或者者復(fù)位異異步通知知(如同同在本章章中異異步通知知一節(jié)節(jié)中討論論的). 注意意直到 Linnux 2.22.4 版本的的內(nèi)核不不正確地地使
29、用這這個(gè)命令令來(lái)修改改 O_SYNNC 標(biāo)標(biāo)志. 因?yàn)閮蓛蓚€(gè)動(dòng)作作都可通通過(guò) ffcnttl 來(lái)來(lái)完成, 沒(méi)有有人真正正使用 FIOOASYYNC 命令, 它在在這里出出現(xiàn)只是是為了完完整性.FIOQQSIZZE 這個(gè)命令令返回一一個(gè)文件件或者目目錄的大大小; 當(dāng)用作作一個(gè)設(shè)設(shè)備文件件, 但但是, 它返回回一個(gè) ENOOTTYY 錯(cuò)誤誤.FIONNBIOO Noon-BBlocckinng II/O(在阻塞和和非阻塞塞操作一節(jié)中中描述). 這這個(gè)調(diào)用用修改在在 fiilp-f_flaags 中的 O_NNONBBLOCCK 標(biāo)標(biāo)志. 給這個(gè)個(gè)系統(tǒng)調(diào)調(diào)用的第第 3 個(gè)參數(shù)數(shù)用作指指示是否否這個(gè)標(biāo)
30、標(biāo)志被置置位或者者清除. (我我們將在在本章看看到這個(gè)個(gè)標(biāo)志的的角色). 注注意常用用的改變變這個(gè)標(biāo)標(biāo)志的方方法是使使用 ffcnttl 系系統(tǒng)調(diào)用用, 使使用 FF_SEETFLL 命令令.列表中的的最后一一項(xiàng)介紹紹了一個(gè)個(gè)新的系系統(tǒng)調(diào)用用, ffcnttl, 它看來(lái)來(lái)象 iiocttl. 事實(shí)上上, ffcnttl 調(diào)調(diào)用非常常類(lèi)似 iocctl, 它也也是獲得得一個(gè)命命令參數(shù)數(shù)和一個(gè)個(gè)額外的的(可選選地)參參數(shù). 它保持持和 iiocttl 獨(dú)獨(dú)立主要要是因?yàn)闉闅v史原原因: 當(dāng) UUnixx 開(kāi)發(fā)發(fā)者面對(duì)對(duì)控制 I/OO 操作作的問(wèn)題題時(shí), 他們決決定文件件和設(shè)備備是不同同的. 那時(shí),
31、有 iocctl 實(shí)現(xiàn)的的唯一設(shè)設(shè)備是 ttyys, 它解釋釋了為什什么 -ENOOTTYY 是標(biāo)標(biāo)準(zhǔn)的對(duì)對(duì)不正確確 iooctll 命令令的回答答. 事事情已經(jīng)經(jīng)改變, 但是是 fccntll 保留留為一個(gè)個(gè)獨(dú)立的的系統(tǒng)調(diào)調(diào)用.6.1.4.使用 iocctl 參數(shù)在看 ssculll 驅(qū)驅(qū)動(dòng)的 iocctl 代碼之之前, 我們需需要涉及及的另一一點(diǎn)是如如何使用用這個(gè)額額外的參參數(shù). 如果它它是一個(gè)個(gè)整數(shù), 就容容易: 它可以以直接使使用. 如果它它是一個(gè)個(gè)指針, 但是是, 必必須小心心些.當(dāng)用一個(gè)個(gè)指針引引用用戶(hù)戶(hù)空間, 我們們必須確確保用戶(hù)戶(hù)地址是是有效的的. 試試圖存取取一個(gè)沒(méi)沒(méi)驗(yàn)證過(guò)過(guò)
32、的用戶(hù)戶(hù)提供的的指針可可能導(dǎo)致致不正確確的行為為, 一一個(gè)內(nèi)核核 ooops, 系統(tǒng)統(tǒng)崩潰, 或者者安全問(wèn)問(wèn)題. 它是驅(qū)驅(qū)動(dòng)的責(zé)責(zé)任來(lái)對(duì)對(duì)每個(gè)它它使用的的用戶(hù)空空間地址址進(jìn)行正正確的檢檢查, 并且返返回一個(gè)個(gè)錯(cuò)誤如如果它是是無(wú)效的的.在第 33 章, 我們們看了 coppy_ffromm_usser 和 ccopyy_too_usser 函數(shù), 它們們可用來(lái)來(lái)安全地地移動(dòng)數(shù)數(shù)據(jù)到和和從用戶(hù)戶(hù)空間. 這些些函數(shù)也也可用在在 iooctll 方法法中, 但是 iocctl 調(diào)用常常常包含含小數(shù)據(jù)據(jù)項(xiàng), 可通過(guò)過(guò)其他方方法更有有效地操操作. 開(kāi)始, 地址址校驗(yàn)(不傳送送數(shù)據(jù))由函數(shù)數(shù) acccess
33、s_ook 實(shí)實(shí)現(xiàn), 它定義義在 :int acccesss_okk(innt ttypee, cconsst vvoidd *aaddrr, uunsiigneed llongg siize); 第一個(gè)參參數(shù)應(yīng)當(dāng)當(dāng)是 VVERIIFY_REAAD 或或者 VVERIIFY_WRIITE, 依據(jù)據(jù)這個(gè)要要進(jìn)行的的動(dòng)作是是否是讀讀用戶(hù)空空間內(nèi)存存區(qū)或者者寫(xiě)它. adddr 參數(shù)持持有一個(gè)個(gè)用戶(hù)空空間地址址, ssizee 是一一個(gè)字節(jié)節(jié)量. 例如, 如果果 iooctll 需要要從用戶(hù)戶(hù)空間讀讀一個(gè)整整數(shù), sizze 是是 siizeoof(iint). 如如果你需需要讀和和寫(xiě)給定定地址, 使
34、用用 VEERIFFY_WWRITTE, 因?yàn)樗?VVERIIRY_REAAD 的的超集.不象大部部分的內(nèi)內(nèi)核函數(shù)數(shù), aacceess_ok 返回一一個(gè)布爾爾值: 1 是是成功(存取沒(méi)沒(méi)問(wèn)題)和 00 是失失敗(存存取有問(wèn)問(wèn)題). 如果果它返回回假, 驅(qū)動(dòng)應(yīng)應(yīng)當(dāng)返回回 -EEFAUULT 給調(diào)用用者.關(guān)于 aacceess_ok有有多個(gè)有有趣的東東西要注注意. 首先, 它不不做校驗(yàn)驗(yàn)內(nèi)存存存取的完完整工作作; 它它只檢查查看這個(gè)個(gè)內(nèi)存引引用是在在這個(gè)進(jìn)進(jìn)程有合合理權(quán)限限的內(nèi)存存范圍中中. 特特別地, acccesss_ook 確確保這個(gè)個(gè)地址不不指向內(nèi)內(nèi)核空間間內(nèi)存. 第22, 大大部分
35、驅(qū)驅(qū)動(dòng)代碼碼不需要要真正調(diào)調(diào)用 aacceess_ok. 后面面描述的的內(nèi)存存存取函數(shù)數(shù)為你負(fù)負(fù)責(zé)這個(gè)個(gè). 但但是, 我們來(lái)來(lái)演示它它的使用用, 以以便你可可見(jiàn)到它它如何完完成.sculll 源源碼利用用了 iiocllt 號(hào)號(hào)中的位位段來(lái)檢檢查參數(shù)數(shù), 在在 swwitcch 之之前:int errr = 0, tmpp;int rettvall = 0;/* * eextrractt thhe ttypee annd nnumbber bittfieeldss, aand donnt deccodee * wwronng ccmdss: rretuurn ENOOTTYY (iinappp
36、roopriiatee iooctll) bbefoore acccesss_okk() */if (_IOOC_TTYPEE(cmmd) != SCUULL_IOCC_MAAGICC) reeturrn -ENOOTTYY;if (_IOOC_NNR(ccmd) SCUULL_IOCC_MAAXNRR) reeturrn -ENOOTTYY;/* * tthe dirrecttionn iss a bittmassk, andd VEERIFFY_WWRITTE ccatcchess R/W * ttrannsfeers. TTypee iis uuserr-orrienntedd, wwh
37、ille * aacceess_ok is kerrnell-orrienntedd, sso tthe connceppt oof reaad andd * wriite iss reeverrsedd */if (_IOOC_DDIR(cmdd) & _IIOC_REAAD) errr = !aacceess_ok(VERRIFYY_WRRITEE, (voiid _usser *)aarg, _IIOC_SIZZE(ccmd);elsee iff (_IOCC_DIIR(ccmd) & _IOOC_WWRITTE) errr = !aacceess_ok(VERRIFYY_REEAD,
38、(vvoidd _useer *)arrg, _IOOC_SSIZEE(cmmd);if (errr) reeturrn -EFAAULTT;在調(diào)用 acccesss_okk 之后后, 驅(qū)驅(qū)動(dòng)可安安全地進(jìn)進(jìn)行真正正的傳輸輸. 加加上 ccopyy_frrom_useer 和和 coopy_to_useer_ 函數(shù), 程序序員可利利用一組組為被最最多使用用的數(shù)據(jù)據(jù)大小(1, 2, 4, 和 88 字節(jié)節(jié))而優(yōu)優(yōu)化過(guò)的的函數(shù). 這些些函數(shù)在在下面列列表中描描述, 它們定定義在 :put_useer(ddatuum, ptrr) _puut_uuserr(daatumm, pptr) 這些宏定定義寫(xiě)
39、 dattum 到用戶(hù)戶(hù)空間; 它們們相對(duì)快快, 并并且應(yīng)當(dāng)當(dāng)被調(diào)用用來(lái)代替替 coopy_to_useer 無(wú)無(wú)論何時(shí)時(shí)要傳送送單個(gè)值值時(shí). 這些宏宏已被編編寫(xiě)來(lái)允允許傳遞遞任何類(lèi)類(lèi)型的指指針到 putt_usser, 只要要它是一一個(gè)用戶(hù)戶(hù)空間地地址. 傳送的的數(shù)據(jù)大大小依賴(lài)賴(lài) prrt 參參數(shù)的類(lèi)類(lèi)型, 并且在在編譯時(shí)時(shí)使用 sizzeoff 和 typpeoff 等編編譯器內(nèi)內(nèi)建宏確確定. 結(jié)果是是, 如如果 pprt 是一個(gè)個(gè) chhar 指針, 傳送送一個(gè)字字節(jié), 以及對(duì)對(duì)于 22, 44, 和和 可能能的 88 字節(jié)節(jié).put_useer 檢檢查來(lái)確確保這個(gè)個(gè)進(jìn)程能能夠?qū)懭肴虢o定
40、的的內(nèi)存地地址. 它在成成功時(shí)返返回 00, 并并且在錯(cuò)錯(cuò)誤時(shí)返返回 -EFAAULTT. _puut_uuserr 進(jìn)行行更少的的檢查(它不調(diào)調(diào)用 aacceess_ok), 但但是仍然然能夠失失敗如果果被指向向的內(nèi)存存對(duì)用戶(hù)戶(hù)是不可可寫(xiě)的. 因此此, _puut_uuserr 應(yīng)當(dāng)當(dāng)只用在在內(nèi)存區(qū)區(qū)已經(jīng)用用 acccesss_ook 檢檢查過(guò)的的時(shí)候.作為一個(gè)個(gè)通用的的規(guī)則, 當(dāng)你你實(shí)現(xiàn)一一個(gè) rreadd 方法法時(shí), 調(diào)用 _pput_useer 來(lái)來(lái)節(jié)省幾幾個(gè)周期期, 或或者當(dāng)你你拷貝幾幾個(gè)項(xiàng)時(shí)時(shí), 因因此, 在第一一次數(shù)據(jù)據(jù)傳送之之前調(diào)用用 acccesss_ook 一一次, 如同上
41、上面 iiocttl 所所示.get_useer(llocaal, ptrr) _geet_uuserr(loocall, pptr) 這些宏定定義用來(lái)來(lái)從用戶(hù)戶(hù)空間接接收單個(gè)個(gè)數(shù)據(jù). 它們們象 pput_useer 和和 _putt_usser, 但是是在相反反方向傳傳遞數(shù)據(jù)據(jù). 獲獲取的值值存儲(chǔ)于于本地變變量 llocaal; 返回值值指出這這個(gè)操作作是否成成功. 再次, _gett_usser 應(yīng)當(dāng)只只用在已已經(jīng)使用用 acccesss_ook 校校驗(yàn)過(guò)的的地址.如果做一一個(gè)嘗試試來(lái)使用用一個(gè)列列出的函函數(shù)來(lái)傳傳送一個(gè)個(gè)不適合合特定大大小的值值, 結(jié)結(jié)果常常常是一個(gè)個(gè)來(lái)自編編譯器的的奇怪
42、消消息, 例如covverssionn too noon-sscallar typpe rrequuestted. 在在這些情情況中, 必須須使用 coppy_tto_uuserr 或者者 coopy_froom_uuserr.6.1.5.兼容性性和受限限操作存取一個(gè)個(gè)設(shè)備由由設(shè)備文文件上的的許可權(quán)權(quán)控制, 并且且驅(qū)動(dòng)正正常地不不涉及到到許可權(quán)權(quán)的檢查查. 但但是, 有些情情形, 在保證證給任何何用戶(hù)對(duì)對(duì)設(shè)備的的讀寫(xiě)許許可的地地方, 一些控控制操作作仍然應(yīng)應(yīng)當(dāng)被拒拒絕. 例如, 不是是所有的的磁帶驅(qū)驅(qū)動(dòng)器的的用戶(hù)都都應(yīng)當(dāng)能能夠設(shè)置置它的缺缺省塊大大小, 并且一一個(gè)已經(jīng)經(jīng)被給予予對(duì)一個(gè)個(gè)磁盤(pán)設(shè)設(shè)
43、備讀寫(xiě)寫(xiě)權(quán)限的的用戶(hù)應(yīng)應(yīng)當(dāng)仍然然可能被被拒絕來(lái)來(lái)格式化化它. 在這樣樣的情況況下, 驅(qū)動(dòng)必必須進(jìn)行行額外的的檢查來(lái)來(lái)確保用用戶(hù)能夠夠進(jìn)行被被請(qǐng)求的的操作.傳統(tǒng)上 uniix 系系統(tǒng)對(duì)超超級(jí)用戶(hù)戶(hù)帳戶(hù)限限制了特特權(quán)操作作. 這這意味著著特權(quán)是是一個(gè)全全有-或或-全無(wú)無(wú)的東西西 - 超級(jí)級(jí)用戶(hù)可可能任意意做任何何事情, 但是是所有其其他的用用戶(hù)被高高度限制制了. Linnux 內(nèi)核提提供了一一個(gè)更加加靈活的的系統(tǒng), 稱(chēng)為為能力. 一個(gè)個(gè)基于能能力的系系統(tǒng)丟棄棄了全有有-或全全無(wú)模式式, 并并且打破破特權(quán)操操作為獨(dú)獨(dú)立的子子類(lèi). 這種方方式, 一個(gè)特特殊的用用戶(hù)(或或者是程程序)可可被授權(quán)權(quán)來(lái)進(jìn)行行
44、一個(gè)特特定的特特權(quán)操作作而不必必泄漏進(jìn)進(jìn)行其他他的, 無(wú)關(guān)的的操作的的能力. 內(nèi)核核在許可可權(quán)管理理上排他他地使用用能力, 并且且輸出 2 個(gè)個(gè)系統(tǒng)調(diào)調(diào)用 ccapgget 和 ccapsset, 來(lái)允允許它們們被從用用戶(hù)空間間管理.全部能力力可在 中找到到. 這這些是對(duì)對(duì)系統(tǒng)唯唯一可用用的能力力; 對(duì)對(duì)于驅(qū)動(dòng)動(dòng)作者或或者系統(tǒng)統(tǒng)管理員員, 不不可能不不修改內(nèi)內(nèi)核源碼碼而來(lái)定定義新的的. 設(shè)設(shè)備驅(qū)動(dòng)動(dòng)編寫(xiě)者者可能感感興趣的的這些能能力的一一個(gè)子集集, 包包括下面面:CAP_DACC_OVVERRRIDEE 這個(gè)能力力來(lái)推翻翻在文件件和目錄錄上的存存取的限限制(數(shù)數(shù)據(jù)存取取控制, 或者者 DAAC
45、).CAP_NETT_ADDMINN 進(jìn)行網(wǎng)絡(luò)絡(luò)管理任任務(wù)的能能力, 包括那那些能夠夠影響網(wǎng)網(wǎng)絡(luò)接口口的.CAP_SYSS_MOODULLE 加載或去去除內(nèi)核核模塊的的能力.CAP_SYSS_RAAWIOO 進(jìn)行 raww II/O 操作的的能力. 例子子包括存存取設(shè)備備端口或或者直接接和 UUSB 設(shè)備通通訊.CAP_SYSS_ADDMINN 一個(gè)捕獲獲-全部部的能力力, 提提供對(duì)許許多系統(tǒng)統(tǒng)管理操操作的存存取.CAP_SYSS_TTTY_CCONFFIG 進(jìn)行 ttty 配置任任務(wù)的能能力.在進(jìn)行一一個(gè)特權(quán)權(quán)操作之之前, 一個(gè)設(shè)設(shè)備驅(qū)動(dòng)動(dòng)應(yīng)當(dāng)檢檢查調(diào)用用進(jìn)程有有合適的的能力; 不這這樣做可
46、可能導(dǎo)致致用戶(hù)進(jìn)進(jìn)程進(jìn)行行非法的的操作, 對(duì)系系統(tǒng)的穩(wěn)穩(wěn)定和安安全有壞壞的后果果. 能能力檢查查是通過(guò)過(guò) caapabble 函數(shù)來(lái)來(lái)進(jìn)行的的(定義義在 ): intt caapabble(intt caapabbiliity); 在 scculll 例子子驅(qū)動(dòng)中中, 任任何用戶(hù)戶(hù)被許可可來(lái)查詢(xún)?cè)?quuanttum 和 qquanntumm 集的的大小. 只有有特權(quán)用用戶(hù), 但是, 可改改變這些些值, 因?yàn)椴徊贿m當(dāng)?shù)牡闹悼赡苣芎軌牡氐赜绊懴迪到y(tǒng)性能能. 當(dāng)當(dāng)需要時(shí)時(shí), iiocttl 的的 scculll 實(shí)現(xiàn)現(xiàn)檢查用用戶(hù)的特特權(quán)級(jí)別別, 如如下: if (! cappablle (CAPP
47、_SYYS_AADMIIN) retturnn -EEPERRM;在這個(gè)任任務(wù)缺乏乏一個(gè)更更加特定定的能力力時(shí), CAPP_SYYS_AADMIIN 被被選擇來(lái)來(lái)做這個(gè)個(gè)測(cè)試.6.1.6.iocctl 命令的的實(shí)現(xiàn)iocttl 的的 scculll 實(shí)現(xiàn)現(xiàn)只傳遞遞設(shè)備的的配置參參數(shù), 并且象象下面這這樣容易易:swittch(cmdd)casee SCCULLL_IOOCREESETT: scculll_quuanttum = SSCULLL_QQUANNTUMM; scculll_qsset = SSCULLL_QQSETT; brreakk;casee SCCULLL_IOOCSQQUAN
48、NTUMM: /* SSet: arrg ppoinnts to thee vaaluee */ iff (! caapabble (CAAP_SSYS_ADMMIN) retturnn -EEPERRM; reetvaal = _gett_usser(scuull_quaantuum, (innt _usser *)aarg); brreakk;casee SCCULLL_IOOCTQQUANNTUMM: /* TTelll: aarg is thee vaaluee */ iff (! caapabble (CAAP_SSYS_ADMMIN) retturnn -EEPERRM; sccu
49、lll_quuanttum = aarg; brreakk;casee SCCULLL_IOOCGQQUANNTUMM: /* GGet: arrg iis ppoinnterr too reesullt */ reetvaal = _putt_usser(scuull_quaantuum, (innt _usser *)aarg); brreakk;casee SCCULLL_IOOCQQQUANNTUMM: /* QQuerry: retturnn itt (iitss poosittivee) */ reeturrn ssculll_qquanntumm;casee SCCULLL_IO
50、OCXQQUANNTUMM: /* eeXchhangge: usee arrg aas ppoinnterr */ iff (! caapabble (CAAP_SSYS_ADMMIN) retturnn -EEPERRM; tmmp = scculll_quuanttum; reetvaal = _gett_usser(scuull_quaantuum, (innt _usser *)aarg); iff (rretvval = 0) rettvall = _pput_useer(ttmp, (iint _uuserr *)argg); brreakk;casee SCCULLL_IOOC
51、HQQUANNTUMM: /* ssHifft: likke TTelll + Queery */ iff (! caapabble (CAAP_SSYS_ADMMIN) retturnn -EEPERRM; tmmp = scculll_quuanttum; scculll_quuanttum = aarg; reeturrn ttmp;defaaultt: /* rreduundaant, ass cmmd wwas cheeckeed aagaiinstt MAAXNRR */ reeturrn -ENOOTTYY;retuurn rettvall;sculll 還還包含 6 個(gè)個(gè)入口項(xiàng)
52、項(xiàng)作用于于 scculll_qsset. 這些些入口項(xiàng)項(xiàng)和給 scuull_quaantuum 的的是一致致的, 并且不不值得展展示出來(lái)來(lái).從調(diào)用者者的觀點(diǎn)點(diǎn)看(即即從用戶(hù)戶(hù)空間), 這這 6 種傳遞遞和接收收參數(shù)的的方法看看來(lái)如下下:int quaantuum;iocttl(ffd,SSCULLL_IIOCSSQUAANTUUM, &quuanttum); /* Sett byy poointter */iocttl(ffd,SSCULLL_IIOCTTQUAANTUUM, quaantuum); /* SSet by vallue */iocttl(ffd,SSCULLL_IIOCGGQU
53、AANTUUM, &quuanttum); /* Gett byy poointter */quanntumm = iocctl(fd,SCUULL_IOCCQQUUANTTUM); /* Gett byy reeturrn vvaluue */iocttl(ffd,SSCULLL_IIOCXXQUAANTUUM, &quuanttum); /* Excchannge by poiinteer */quanntumm = iocctl(fd,SCUULL_IOCCHQUUANTTUM, quuanttum); /* EExchhangge bby vvaluue */當(dāng)然, 一個(gè)正正常的驅(qū)驅(qū)動(dòng)
54、不可可能實(shí)現(xiàn)現(xiàn)這樣一一個(gè)調(diào)用用模式的的混合體體. 我我們這里里這樣做做只是為為了演示示做事情情的不同同方式. 但是是, 正正常地, 數(shù)據(jù)據(jù)交換將將一致地地進(jìn)行, 通過(guò)過(guò)指針或或者通過(guò)過(guò)值, 并且要要避免混混合這 2 種種技術(shù).6.1.7.不用 iocctl 的設(shè)備備控制有時(shí)控制制設(shè)備最最好是通通過(guò)寫(xiě)控控制序列列到設(shè)備備自身來(lái)來(lái)實(shí)現(xiàn). 例如如, 這這個(gè)技術(shù)術(shù)用在控控制臺(tái)驅(qū)驅(qū)動(dòng)中, 這里里所謂的的 esscappe 序序列被用用來(lái)移動(dòng)動(dòng)光標(biāo), 改變變?nèi)笔〉牡念伾? 或者者進(jìn)行其其他的配配置任務(wù)務(wù). 這這樣實(shí)現(xiàn)現(xiàn)設(shè)備控控制的好好處是用用戶(hù)可僅僅僅通過(guò)過(guò)寫(xiě)數(shù)據(jù)據(jù)控制設(shè)設(shè)備, 不必使使用(或或者有時(shí)時(shí)候
55、寫(xiě))只為配配置設(shè)備備而建立立的程序序. 當(dāng)當(dāng)設(shè)備可可這樣來(lái)來(lái)控制, 發(fā)出出命令的的程序甚甚至常常常不需要要運(yùn)行在在和它要要控制的的設(shè)備所所在的同同一個(gè)系系統(tǒng)上.例如, settterrm 程程序作用用于控制制臺(tái)(或或者其他他終端)配置, 通過(guò)過(guò)打印 esccapee 序列列. 控控制程序序可位于于和被控控制的設(shè)設(shè)備不同同的一臺(tái)臺(tái)計(jì)算機(jī)機(jī)上, 因?yàn)橐灰粋€(gè)簡(jiǎn)單單的數(shù)據(jù)據(jù)流重定定向可完完成這個(gè)個(gè)配置工工作. 這是每每次你運(yùn)運(yùn)行一個(gè)個(gè)遠(yuǎn)程 ttyy 會(huì)話話時(shí)所發(fā)發(fā)生的事事情: esccapee 序列列在遠(yuǎn)端端被打印印但是影影響到本本地的 ttyy; 然然而, 這個(gè)技技術(shù)不局局限于 ttyys.通過(guò)打印
56、印來(lái)控制制的缺點(diǎn)點(diǎn)是它給給設(shè)備增增加了策策略限制制; 例例如, 它僅僅僅當(dāng)你確確信在正正常操作作時(shí)控制制序列不不會(huì)出現(xiàn)現(xiàn)在正被被寫(xiě)入設(shè)設(shè)備的數(shù)數(shù)據(jù)中. 這對(duì)對(duì)于 tttyss 只是是部分正正確的. 盡管管一個(gè)文文本顯示示意味著著只顯示示 ASSCIII 字符符, 有有時(shí)控制制字符可可潛入正正被寫(xiě)入入的數(shù)據(jù)據(jù)中, 并且可可能, 因此, 影響響控制臺(tái)臺(tái)的配置置. 例例如, 這可能能發(fā)生在在你顯示示一個(gè)二二進(jìn)制文文件到屏屏幕時(shí); 產(chǎn)生生的亂碼碼可能包包含任何何東西, 并且且最后你你常常在在你的控控制臺(tái)上上出現(xiàn)錯(cuò)錯(cuò)誤的字字體.通過(guò)寫(xiě)來(lái)來(lái)控制是是當(dāng)然的的使用方方法了, 對(duì)于于不用傳傳送數(shù)據(jù)據(jù)而只是是響應(yīng)
57、命命令的設(shè)設(shè)備, 例如遙遙控設(shè)備備.例如, 被你們們作者當(dāng)當(dāng)中的一一個(gè)編寫(xiě)寫(xiě)來(lái)好玩玩的驅(qū)動(dòng)動(dòng), 移移動(dòng)一個(gè)個(gè) 2 軸上的的攝像機(jī)機(jī). 在在這個(gè)驅(qū)驅(qū)動(dòng)里, 這個(gè)個(gè)設(shè)備備是一一對(duì)老式式步進(jìn)電電機(jī), 它們不不能真正正讀或?qū)憣?xiě). 給給一個(gè)步步進(jìn)電機(jī)機(jī)發(fā)送送數(shù)據(jù)流流的概概念沒(méi)有有任何意意義. 在這個(gè)個(gè)情況下下, 驅(qū)驅(qū)動(dòng)解釋釋正被寫(xiě)寫(xiě)入的數(shù)數(shù)據(jù)作為為 ASSCIII 命令令并且轉(zhuǎn)轉(zhuǎn)換這個(gè)個(gè)請(qǐng)求為為脈沖序序列, 來(lái)操縱縱步進(jìn)電電機(jī). 這個(gè)概概念類(lèi)似似于, 有些, 你發(fā)發(fā)給貓的的 ATT 命令令來(lái)建立立通訊, 主要要的不同同是和貓貓通訊的的串口必必須也傳傳送真正正的數(shù)據(jù)據(jù). 直直接設(shè)備備控制的的好處是是你可以
58、以使用 catt 來(lái)移移動(dòng)攝像像機(jī), 而不必必寫(xiě)和編編譯特殊殊的代碼碼來(lái)發(fā)出出 iooctll 調(diào)用用.當(dāng)編寫(xiě)面面向命令令的驅(qū)動(dòng)動(dòng), 沒(méi)沒(méi)有理由由實(shí)現(xiàn) iocctl 命令. 一個(gè)個(gè)解釋器器中的額額外命令令更容易易實(shí)現(xiàn)并并使用.有時(shí), 然而, 你可可能選擇擇使用其其他的方方法:不不必轉(zhuǎn)變變 wrritee 方法法為一個(gè)個(gè)解釋器器和避免免 iooctll, 你你可能選選擇完全全避免寫(xiě)寫(xiě)并且專(zhuān)專(zhuān)門(mén)使用用 iooctll 命令令, 而而實(shí)現(xiàn)驅(qū)驅(qū)動(dòng)為使使用一個(gè)個(gè)特殊的的命令行行工具來(lái)來(lái)發(fā)送這這些命令令到驅(qū)動(dòng)動(dòng). 這這個(gè)方法法轉(zhuǎn)移復(fù)復(fù)雜性從從內(nèi)核空空間到用用戶(hù)空間間, 這這里可能能更易處處理, 并且?guī)蛶椭?/p>
59、保持持驅(qū)動(dòng)小小, 而而拒絕使使用簡(jiǎn)單單的 ccat 或者 echho 命命令. 但但是, 這個(gè)文文件的維維護(hù)在后后來(lái)有些些少見(jiàn)了了. 實(shí)實(shí)際上, 所有有的當(dāng)前前使用的的 liibc 實(shí)現(xiàn)(包括 uCllibcc) 僅僅將 -40995 到到 -11 的值值當(dāng)作錯(cuò)錯(cuò)誤碼. 不幸幸的是, 能夠夠返回大大的負(fù)數(shù)數(shù)而不是是小的, 沒(méi)有有多大用用處.6.2.阻塞 I/OO回顧第 3 章章, 我我們看到到如何實(shí)實(shí)現(xiàn) rreadd 和 wriite 方法. 在此此, 但但是, 我們跳跳過(guò)了一一個(gè)重要要的問(wèn)題題:一個(gè)個(gè)驅(qū)動(dòng)當(dāng)當(dāng)它無(wú)法法立刻滿(mǎn)滿(mǎn)足請(qǐng)求求應(yīng)當(dāng)如如何響應(yīng)應(yīng)? 一一個(gè)對(duì) reaad 的的調(diào)用可可能當(dāng)沒(méi)
60、沒(méi)有數(shù)據(jù)據(jù)時(shí)到來(lái)來(lái), 而而以后會(huì)會(huì)期待更更多的數(shù)數(shù)據(jù). 或者一一個(gè)進(jìn)程程可能試試圖寫(xiě), 但是是你的設(shè)設(shè)備沒(méi)有有準(zhǔn)備好好接受數(shù)數(shù)據(jù), 因?yàn)槟隳愕妮敵龀鼍彌_滿(mǎn)滿(mǎn)了. 調(diào)用進(jìn)進(jìn)程往往往不關(guān)心心這種問(wèn)問(wèn)題; 程序員員只希望望調(diào)用 reaad 或或 wrritee 并且且使調(diào)用用返回, 在必必要的工工作已完完成后. 這樣樣, 在在這樣的的情形中中, 你你的驅(qū)動(dòng)動(dòng)應(yīng)當(dāng)(缺省地地)阻塞塞進(jìn)程, 使它它進(jìn)入睡睡眠直到到請(qǐng)求可可繼續(xù). 本節(jié)展示示如何使使一個(gè)進(jìn)進(jìn)程睡眠眠并且之之后再次次喚醒它它. 如如常, 但是, 我們們必須首首先解釋釋幾個(gè)概概念.6.2.1.睡眠的的介紹對(duì)于一個(gè)個(gè)進(jìn)程睡眠意味著著什么? 當(dāng)一一
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度旅游服務(wù)合同結(jié)算范本6篇
- 二零二五年度國(guó)際貿(mào)易欺詐風(fēng)險(xiǎn)預(yù)警與應(yīng)對(duì)合同3篇
- 海南醫(yī)學(xué)院《審計(jì)》2023-2024學(xué)年第一學(xué)期期末試卷
- 2025年度深基坑支護(hù)土石方工程承包合作協(xié)議書(shū)2篇
- 二零二五年度房地產(chǎn)開(kāi)發(fā)商與裝修公司之間的裝修合同3篇
- 邊坡工程課程設(shè)計(jì)規(guī)范
- 英文課程設(shè)計(jì)理念
- 淘寶電商課程設(shè)計(jì)
- 貴州水質(zhì)工程課程設(shè)計(jì)
- 二零二五年度數(shù)據(jù)中心建設(shè)服務(wù)合同2篇
- 精彩的儲(chǔ)運(yùn)部年終總結(jié)
- 山西省太原市重點(diǎn)中學(xué)2025屆物理高一第一學(xué)期期末統(tǒng)考試題含解析
- Python開(kāi)發(fā)工程師招聘筆試題及解答(某大型國(guó)企)
- 2024年農(nóng)民職業(yè)農(nóng)業(yè)素質(zhì)技能考試題庫(kù)(附含答案)
- 妊娠期高血糖診治指南
- 2024壓鑄機(jī)安全技術(shù)規(guī)范
- 綿陽(yáng)小升初數(shù)學(xué)試題-(綿中英才學(xué)校)
- 數(shù)據(jù)中心數(shù)據(jù)中心建設(shè)項(xiàng)目電氣工程設(shè)計(jì)方案
- 廣東省深圳市2022年中考英語(yǔ)真題(含答案)
- 四川省瀘州市(2024年-2025年小學(xué)四年級(jí)語(yǔ)文)統(tǒng)編版期末考試(上學(xué)期)試卷及答案
- 新版《鐵道概論》考試復(fù)習(xí)試題庫(kù)(含答案)
評(píng)論
0/150
提交評(píng)論