高級(jí)字符驅(qū)動(dòng)操作說明_第1頁
高級(jí)字符驅(qū)動(dòng)操作說明_第2頁
高級(jí)字符驅(qū)動(dòng)操作說明_第3頁
高級(jí)字符驅(qū)動(dòng)操作說明_第4頁
高級(jí)字符驅(qū)動(dòng)操作說明_第5頁
已閱讀5頁,還剩90頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、 HYPERLINK 更多企業(yè)學(xué)學(xué)院: 中小企業(yè)業(yè)管理全全能版183套講講座+8897000份資料總經(jīng)理、高高層管理理49套講座座+1663888份資料中層管理理學(xué)院46套講座座+60020份份資料國學(xué)智慧慧、易經(jīng)經(jīng)46套講座座人力資源源學(xué)院56套講座座+2771233份資料各階段員員工培訓(xùn)訓(xùn)學(xué)院77套講座座+ 3324份份資料員工管理理企業(yè)學(xué)學(xué)院67套講座座+ 887200份資料工廠生產(chǎn)產(chǎn)管理學(xué)學(xué)院52套講座座+ 1139220份資料財(cái)務(wù)管理理學(xué)院53套講座座+ 1179445份資料銷售經(jīng)理理學(xué)院56套講座座+ 1143550份資料銷售人員員培訓(xùn)學(xué)學(xué)院72套講座座+ 448799份資料(20

2、088-099-288 166:288) 分類: 第 6 章章 高級(jí)級(jí)字符驅(qū)驅(qū)動(dòng)操作作在第 3 章, 我們建建立了一一個(gè)完整整的設(shè)備備驅(qū)動(dòng), 用戶戶可用來來寫入和和讀取. 但是是一個(gè)真真正的設(shè)設(shè)備常常常提供比比同步讀讀和寫更更多的功功能. 現(xiàn)在我我們已裝裝備有調(diào)調(diào)試工具具如果發(fā)發(fā)生錯(cuò)誤誤, 并并且一個(gè)個(gè)牢固的的并發(fā)的的理解來來幫助避避免事情情進(jìn)入錯(cuò)錯(cuò)誤- 我們們可安全全地前進(jìn)進(jìn)并且創(chuàng)創(chuàng)建一個(gè)個(gè)更高級(jí)級(jí)的驅(qū)動(dòng)動(dòng).本章檢查幾幾個(gè)你需需要理解解的概念念來編寫寫全特性性的字符符設(shè)備驅(qū)驅(qū)動(dòng). 我們從從實(shí)現(xiàn) iocctl 系統(tǒng)調(diào)調(diào)用開始始, 它它是用作作設(shè)備控控制的普普通接口口. 接接著我們們進(jìn)入各各種和

3、用用戶空間間同步的的方法; 在本本章結(jié)尾尾, 你你有一個(gè)個(gè)充分的的認(rèn)識(shí)對(duì)對(duì)于如何何使進(jìn)程程睡眠(并且喚喚醒它們們), 實(shí)現(xiàn)非非阻塞的的 I/O, 并且通通知用戶戶空間當(dāng)當(dāng)你的設(shè)設(shè)備可用用來讀或或?qū)? 我們以以查看如如何在驅(qū)驅(qū)動(dòng)中實(shí)實(shí)現(xiàn)幾個(gè)個(gè)不同的的設(shè)備存存取策略略來結(jié)束束.這里討論的的概念通通過 ssculll 驅(qū)驅(qū)動(dòng)的幾幾個(gè)修改改版本來來演示. 再一一次, 所有的的都使用用內(nèi)存中中的虛擬擬設(shè)備來來實(shí)現(xiàn), 因此此你可自自己試驗(yàn)驗(yàn)這些代代碼而不不必使用用任何特特別的硬硬件. 到此為為止, 你可能能在想親親手使用用真正的的硬件, 但是是那將必必須等到到第 99 章.6.1.iocctl 接口大部分

4、驅(qū)動(dòng)動(dòng)需要 - 除了讀讀寫設(shè)備備的能力力 - 通過過設(shè)備驅(qū)驅(qū)動(dòng)進(jìn)行行各種硬硬件控制制的能力力. 大大部分設(shè)設(shè)備可進(jìn)進(jìn)行超出出簡單的的數(shù)據(jù)傳傳輸之外外的操作作; 用用戶空間間必須常常常能夠夠請(qǐng)求, 例如如, 設(shè)設(shè)備鎖上上它的門門, 彈彈出它的的介質(zhì), 報(bào)告告錯(cuò)誤信信息, 改變波波特率, 或者者自我銷銷毀. 這些操操作常常常通過 iocctl 方法來來支持, 它通通過相同同名子的的系統(tǒng)調(diào)調(diào)用來實(shí)實(shí)現(xiàn).在用戶空間間, iiocttl 系系統(tǒng)調(diào)用用有下面面的原型型:int iiocttl(iint fd, unnsiggnedd loong cmdd, .); 這個(gè)原型由由于這些些點(diǎn)而凸凸現(xiàn)于 Uni

5、ix 系系統(tǒng)調(diào)用用列表, 這些些點(diǎn)常常常表示函函數(shù)有數(shù)數(shù)目不定定的參數(shù)數(shù). 在在實(shí)際系系統(tǒng)中, 但是是, 一一個(gè)系統(tǒng)統(tǒng)調(diào)用不不能真正正有變數(shù)數(shù)目的參參數(shù). 系統(tǒng)調(diào)調(diào)用必須須有一個(gè)個(gè)很好定定義的原原型, 因?yàn)橛糜脩舫绦蛐蚩纱嫒∪∷鼈冎恢荒芡ㄟ^過硬件的的門. 因因此, 原型中中的點(diǎn)不不表示一一個(gè)變數(shù)數(shù)目的參參數(shù), 而是一一個(gè)單個(gè)個(gè)可選的的參數(shù), 傳統(tǒng)統(tǒng)上標(biāo)識(shí)識(shí)為 ccharr *aargpp. 這這些點(diǎn)在在那里只只是為了了阻止在在編譯時(shí)時(shí)的類型型檢查. 第 3 個(gè)個(gè)參數(shù)的的實(shí)際特特點(diǎn)依賴賴所發(fā)出出的特定定的控制制命令( 第 2 個(gè)個(gè)參數(shù) ). 一些命命令不用用參數(shù), 一些些用一個(gè)個(gè)整數(shù)值值, 以以

6、及一些些使用指指向其他他數(shù)據(jù)的的指針. 使用用一個(gè)指指針是傳傳遞任意意數(shù)據(jù)到到 iooctll 調(diào)用用的方法法; 設(shè)設(shè)備接著著可與用用戶空間間交換任任何數(shù)量量的數(shù)據(jù)據(jù).ioctll 調(diào)用用的非結(jié)結(jié)構(gòu)化特特性使它它在內(nèi)核核開發(fā)者者中失寵寵. 每每個(gè) iiocttl 命命令, 基本上上, 是是一個(gè)單單獨(dú)的, 常常常無文檔檔的系統(tǒng)統(tǒng)調(diào)用, 并且且沒有方方法以任任何類型型的全面面的方式式核查這這些調(diào)用用. 也也難于使使非結(jié)構(gòu)構(gòu)化的 iocctl 參數(shù)在在所有系系統(tǒng)上一一致工作作; 例例如, 考慮運(yùn)運(yùn)行在 32-位模式式的一個(gè)個(gè)用戶進(jìn)進(jìn)程的 64-位 系系統(tǒng). 結(jié)果, 有很很大的壓壓力來實(shí)實(shí)現(xiàn)混雜雜的控

7、制制操作, 只通通過任何何其他的的方法. 可能能的選擇擇包括嵌嵌入命令令到數(shù)據(jù)據(jù)流(本本章稍后后我們將將討論這這個(gè)方法法)或者者使用虛虛擬文件件系統(tǒng), 要么么是 ssysffs 要要么是設(shè)設(shè)備特定定的文件件系統(tǒng). (我我們將在在 144 章看看看 ssysffs). 但是是, 事事實(shí)是 iocctl 常常是是最容易易的和最最直接的的選擇,對(duì)于真真正的設(shè)設(shè)備操作作.ioctll 驅(qū)動(dòng)動(dòng)方法有有和用戶戶空間版版本不同同的原型型:int (*iooctll) (strructt innodee *iinodde, strructt fiile *fiilp, unnsiggnedd innt ccm

8、d, unnsiggnedd loong argg);inodee 和 fillp 指指針是對(duì)對(duì)應(yīng)應(yīng)用用程序傳傳遞的文文件描述述符 ffd 的的值, 和傳遞遞給 oopenn 方法法的相同同參數(shù). cmmd 參參數(shù)從用用戶那里里不改變變地傳下下來, 并且可可選的參參數(shù) aarg 參數(shù)以以一個(gè) unssignned lonng 的的形式傳傳遞, 不管它它是否由由用戶給給定為一一個(gè)整數(shù)數(shù)或一個(gè)個(gè)指針. 如果果調(diào)用程程序不傳傳遞第 3 個(gè)個(gè)參數(shù), 被驅(qū)驅(qū)動(dòng)操作作收到的的 arrg 值值是無定定義的. 因?yàn)闉轭愋蜋z檢查在這這個(gè)額外外參數(shù)上上被關(guān)閉閉, 編編譯器不不能警告告你如果果一個(gè)無無效的參參數(shù)被傳

9、傳遞給 iocctl, 并且且任何關(guān)關(guān)聯(lián)的錯(cuò)錯(cuò)誤將難難以查找找.如果你可能能想到的的, 大大部分 iocctl 實(shí)現(xiàn)包包括一個(gè)個(gè)大的 swiitchh 語句句來根據(jù)據(jù) cmmd 參參數(shù), 選擇正正確的做做法. 不同的的命令有有不同的的數(shù)值, 它們們常常被被給予符符號(hào)名來來簡化編編碼. 符號(hào)名名通過一一個(gè)預(yù)處處理定義義來安排排. 定定制的驅(qū)驅(qū)動(dòng)常常常聲明這這樣的符符號(hào)在它它們的頭頭文件中中; ssculll.hh 為 scuull 聲明它它們. 用戶程程序必須須, 當(dāng)當(dāng)然, 包含那那個(gè)頭文文件來存存取這些些符號(hào).6.1.11.選擇 iocctl 命令在為 iooctll 編寫寫代碼之之前, 你需

10、要要選擇對(duì)對(duì)應(yīng)命令令的數(shù)字字. 許許多程序序員的第第一個(gè)本本能的反反應(yīng)是選選擇一組組小數(shù)從從0或11開始, 并且且從此開開始向上上. 但但是, 有充分分的理由由不這樣樣做. iocctl 命令數(shù)數(shù)字應(yīng)當(dāng)當(dāng)在這個(gè)個(gè)系統(tǒng)是是唯一的的, 為為了阻止止向錯(cuò)誤誤的設(shè)備備發(fā)出正正確的命命令而引引起的錯(cuò)錯(cuò)誤. 這樣的的不匹配配不會(huì)不不可能發(fā)發(fā)生, 并且一一個(gè)程序序可能發(fā)發(fā)現(xiàn)它自自己試圖圖改變一一個(gè)非串串口輸入入系統(tǒng)的的波特率率, 例例如一個(gè)個(gè) FIIFO 或者一一個(gè)音頻頻設(shè)備. 如果果這樣的的 iooctll 號(hào)是是唯一的的, 這這個(gè)應(yīng)用用程序得得到一個(gè)個(gè) EIINVAAL 錯(cuò)錯(cuò)誤而不不是繼續(xù)續(xù)做不應(yīng)應(yīng)當(dāng)做

11、的的事情.為幫助程序序員創(chuàng)建建唯一的的 iooctll 命令令代碼, 這些些編碼已已被劃分分為幾個(gè)個(gè)位段. Liinuxx 的第第一個(gè)版版本使用用 166-位數(shù)數(shù): 高高 8 位是關(guān)關(guān)聯(lián)這個(gè)個(gè)設(shè)備的的魔數(shù), 低 88 位是是一個(gè)順順序號(hào), 在設(shè)設(shè)備內(nèi)唯唯一. 這樣做做是因?yàn)闉?Liinuss 是無能的(他他自己的的話); 一個(gè)個(gè)更好的的位段劃劃分僅在在后來被被設(shè)想. 不幸幸的是, 許多多驅(qū)動(dòng)仍仍然使用用老傳統(tǒng)統(tǒng). 它它們不得得不: 改變命命令編碼碼會(huì)破壞壞大量的的二進(jìn)制制程序,并且這這不是內(nèi)內(nèi)核開發(fā)發(fā)者愿意意見到的的.根據(jù) Liinuxx 內(nèi)核核慣例來來為你的的驅(qū)動(dòng)選選擇 iiocttl 號(hào)號(hào)

12、, 你你應(yīng)當(dāng)首首先檢查查 inncluude/asmm/iooctll.h 和 DDocuumenntattionn/iooctll-nuumbeer.ttxt. 這個(gè)個(gè)頭文件件定義你你將使用用的位段段: ttypee(魔數(shù)數(shù)), 序號(hào), 傳輸輸方向, 和參參數(shù)大小小. iiocttl-nnumbber.txtt 文件件列舉了了在內(nèi)核核中使用用的魔數(shù)數(shù), 因此此你將可可選擇你你自己的的魔數(shù)并并且避免免交疊. 這個(gè)個(gè)文本文文件也列列舉了為為什么應(yīng)應(yīng)當(dāng)使用用慣例的的原因.定義 iooctll 命令令號(hào)的正正確方法法使用 4 個(gè)個(gè)位段, 它們們有下列列的含義義. 這這個(gè)列表表中介紹紹的新符符號(hào)定義義

13、在 .type 魔數(shù). 只只是選擇擇一個(gè)數(shù)數(shù)(在參參考了 iocctl-nummberr.txxt之后后)并且且使用它它在整個(gè)個(gè)驅(qū)動(dòng)中中. 這這個(gè)成員員是 88 位寬寬(_IIOC_TYPPEBIITS). numbeer 序(順序)號(hào). 它是 8 位位(_IIOC_NRBBITSS)寬. direcctioon 數(shù)據(jù)傳送的的方向,如果這這個(gè)特殊殊的命令令涉及數(shù)數(shù)據(jù)傳送送. 可可能的值值是 _IOCC_NOONE(沒有數(shù)數(shù)據(jù)傳輸輸), _IOOC_RREADD, _IOCC_WRRITEE, 和和 _IIOC_REAAD|_IOCC_WRRITEE (數(shù)數(shù)據(jù)在22個(gè)方向向被傳送送). 數(shù)據(jù)傳傳

14、送是從從應(yīng)用程程序的觀觀點(diǎn)來看看待的; _IIOC_REAAD 意意思是從從設(shè)備讀讀, 因因此設(shè)備備必須寫寫到用戶戶空間. 注意意這個(gè)成成員是一一個(gè)位掩掩碼, 因此 _IOOC_RREADD 和 _IOOC_WWRITTE 可可使用一一個(gè)邏輯輯 ANND 操操作來抽抽取.size 涉及到的用用戶數(shù)據(jù)據(jù)的大小小. 這這個(gè)成員員的寬度度是依賴賴體系的的, 但但是常常常是 113 或或者 114 位位. 你你可為你你的特定定體系在在宏 _IOCC_SIIZEBBITSS 中找找到它的的值. 你使用用這個(gè) sizze 成成員不是是強(qiáng)制的的 - 內(nèi)核不不檢查它它 - 但是是它是一一個(gè)好主主意. 正確使使

15、用這個(gè)個(gè)成員可可幫助檢檢測用戶戶空間程程序的錯(cuò)錯(cuò)誤并使使你實(shí)現(xiàn)現(xiàn)向后兼兼容, 如果你你曾需要要改變相相關(guān)數(shù)據(jù)據(jù)項(xiàng)的大大小. 如果你你需要更更大的數(shù)數(shù)據(jù)結(jié)構(gòu)構(gòu), 但但是, 你可忽忽略這個(gè)個(gè) siize 成員. 我們們很快見見到如何何使用這這個(gè)成員員.頭文件 , 它它包含在在 中中, 定定義宏來來幫助建建立命令令號(hào), 如下: _IIO(ttypee,nrr)(給給沒有參參數(shù)的命命令), _IIOR(typpe, nree, ddataatyppe)(給從驅(qū)驅(qū)動(dòng)中讀讀數(shù)據(jù)的的), _IOOW(ttypee,nrr,daatattypee)(給給寫數(shù)據(jù)據(jù)), 和 _IOWWR(ttypee,nrr,d

16、aatattypee)(給給雙向傳傳送). tyype 和 nnumbber 成員作作為參數(shù)數(shù)被傳遞遞, 并并且 ssizee 成員員通過應(yīng)應(yīng)用 ssizeeof 到 ddataatyppe 參參數(shù)而得得到.這個(gè)頭文件件還定義義宏, 可被用用在你的的驅(qū)動(dòng)中中來解碼碼這個(gè)號(hào)號(hào): _IOCC_DIIR(nnr), _IIOC_TYPPE(nnr), _IIOC_NR(nr), 和和 _IIOC_SIZZE(nnr). 我們們不進(jìn)入入任何這這些宏的的細(xì)節(jié), 因?yàn)闉轭^文件件是清楚楚的, 并且在在本節(jié)稍稍后有例例子代碼碼展示.這里是一些些 iooctll 命令令如何在在 scculll 被定定義的. 特

17、別別地, 這些命命令設(shè)置置和獲得得驅(qū)動(dòng)的的可配置置參數(shù)./* Usse k as maggic nummberr */#defiine SCUULL_IOCC_MAAGICC kk/* Plleasse uuse a ddifffereent 8-bbit nummberr inn yoour codde */#defiine SCUULL_IOCCRESSET _IOO(SCCULLL_IOOC_MMAGIIC, 0)/* * S meaans Seet thrrouggh aa pttr, * T meaans Teell diirecctlyy wiith thee arrgumment

18、t vaaluee * G meaans Geet: reeplyy byy seettiing thrrouggh aa poointter * Q meaans Quueryy: ressponnse is on thee reeturrn vvaluue * X meaans eXXchaangee: swiitchh G andd S atoomiccallly * H meaans sHHiftt: swiitchh T andd Q atoomiccallly */#defiine SCUULL_IOCCSQUUANTTUM _IOOW(SSCULLL_IIOC_MAGGIC, 1

19、, innt)#defiine SCUULL_IOCCSQSSET _IOOW(SSCULLL_IIOC_MAGGIC, 2, innt)#defiine SCUULL_IOCCTQUUANTTUM _IOO(SCCULLL_IOOC_MMAGIIC, 3)#defiine SCUULL_IOCCTQSSET _IOO(SCCULLL_IOOC_MMAGIIC, 4)#defiine SCUULL_IOCCGQUUANTTUM _IOOR(SSCULLL_IIOC_MAGGIC, 5, innt)#defiine SCUULL_IOCCGQSSET _IOOR(SSCULLL_IIOC_MAG

20、GIC, 6, innt)#defiine SCUULL_IOCCQQUUANTTUM _IOO(SCCULLL_IOOC_MMAGIIC, 7)#defiine SCUULL_IOCCQQSSET _IOO(SCCULLL_IOOC_MMAGIIC, 8)#defiine SCUULL_IOCCXQUUANTTUM _IOOWR(SCUULL_IOCC_MAAGICC, 99, iint)#defiine SCUULL_IOCCXQSSET _IOOWR(SCUULL_IOCC_MAAGICC,100, iint)#defiine SCUULL_IOCCHQUUANTTUM _IOO(SCC

21、ULLL_IOOC_MMAGIIC, 11)#defiine SCUULL_IOCCHQSSET _IOO(SCCULLL_IOOC_MMAGIIC, 12)#defiine SCUULL_IOCC_MAAXNRR 144真正的源文文件定義義幾個(gè)額額外的這這里沒有有出現(xiàn)的的命令.我們選擇實(shí)實(shí)現(xiàn) 22 種方方法傳遞遞整數(shù)參參數(shù): 通過指指針和通通過明確確的值(盡管, 由于于一個(gè)已已存在的的慣例, ioocltt 應(yīng)當(dāng)當(dāng)通過指指針交換換值). 類似似地, 2 種種方法被被用來返返回一個(gè)個(gè)整數(shù)值值:通過過指針和和通過設(shè)設(shè)置返回回值. 這個(gè)有有效只要要返回值值是一個(gè)個(gè)正的整整數(shù); 如同你你現(xiàn)在所所知道

22、的的, 在在從任何何系統(tǒng)調(diào)調(diào)用返回回時(shí), 一個(gè)正正值被保保留(如如同我們們?cè)?rreadd 和 wriite 中見到到的), 而一一個(gè)負(fù)值值被看作作一個(gè)錯(cuò)錯(cuò)誤并且且被用來來在用戶戶空間設(shè)設(shè)置 eerrnno.exchhangge和和shhiftt操作作對(duì)于 scuull 沒有特特別的用用處. 我們實(shí)實(shí)現(xiàn)eexchhangge來來顯示驅(qū)驅(qū)動(dòng)如何何結(jié)合獨(dú)獨(dú)立的操操作到單單個(gè)的原原子的操操作, 并且shiift來連接接teell和qquerry. 有時(shí)時(shí)需要象象這樣的的原子的的測試-和-設(shè)設(shè)置操作作, 特特別地, 當(dāng)應(yīng)應(yīng)用程序序需要設(shè)設(shè)置和釋釋放鎖.命令的明確確的序號(hào)號(hào)沒有特特別的含含義. 它只用用

23、來區(qū)分分命令. 實(shí)際際上, 你甚至至可使用用相同的的序號(hào)給給一個(gè)讀讀命令和和一個(gè)寫寫命令, 因?yàn)闉閷?shí)際的的 iooctll 號(hào)在在方向向位是是不同的的, 但但是你沒沒有理由由這樣做做. 我我們選擇擇在任何何地方不不使用命命令的序序號(hào)除了了聲明中中, 因因此我們們不分配配一個(gè)返返回值給給它. 這就是是為什么么明確的的號(hào)出現(xiàn)現(xiàn)在之前前給定的的定義中中. 這這個(gè)例子子展示了了一個(gè)使使用命令令號(hào)的方方法, 但是你你有自由由不這樣樣做.除了少數(shù)幾幾個(gè)預(yù)定定義的命命令(馬馬上就討討論), iooctll 的 cmdd 參數(shù)數(shù)的值當(dāng)當(dāng)前不被被內(nèi)核使使用, 并且在在將來也也很不可可能. 因此, 你可可以, 如

24、果你你覺得懶懶, 避避免前面面展示的的復(fù)雜的的聲明并并明確聲聲明一組組調(diào)整數(shù)數(shù)字. 另一方方面, 如果你你做了, 你不不會(huì)從使使用這些些位段中中獲益, 并且且你會(huì)遇遇到困難難如果你你曾提交交你的代代碼來包包含在主主線內(nèi)核核中. 頭文件件 是這這個(gè)老式式方法的的例子, 使用用 166-位的的調(diào)整值值來定義義 iooctll 命令令. 那那個(gè)源代代碼依靠靠調(diào)整數(shù)數(shù)因?yàn)槭故褂媚莻€(gè)個(gè)時(shí)候遵遵循的慣慣例, 不是由由于懶惰惰. 現(xiàn)現(xiàn)在改變變它可能能導(dǎo)致無無理由的的不兼容容.6.1.22.返回值值ioctll 的實(shí)實(shí)現(xiàn)常常常是一個(gè)個(gè) swwitcch 語語句, 基于命命令號(hào). 但是是當(dāng)命令令號(hào)沒有有匹配一一

25、個(gè)有效效的操作作時(shí)缺省省的選擇擇應(yīng)當(dāng)是是什么? 這個(gè)個(gè)問題是是有爭議議的. 幾個(gè)內(nèi)內(nèi)核函數(shù)數(shù)返回 -ENNIVAAL(Invvaliid aarguumennt), 它它有意義義是因?yàn)闉槊顓?shù)確實(shí)實(shí)不是一一個(gè)有效效的. POSSIX 標(biāo)準(zhǔn), 但是是, 說說如果一一個(gè)不合合適的 iocctl 命令被被發(fā)出, 那么么 -EENOTTTY 應(yīng)當(dāng)被被返回. 這個(gè)個(gè)錯(cuò)誤碼碼被 CC 庫解解釋為設(shè)備的的不適當(dāng)當(dāng)?shù)?iiocttl, 這常常常正是是程序員員需要聽聽到的. 然而而, 它它仍然是是相當(dāng)普普遍的來來返回 -EIINVAAL, 對(duì)于響響應(yīng)一個(gè)個(gè)無效的的 iooctll 命令令.6.1.33.預(yù)定

26、義義的命令令盡管 iooctll 系統(tǒng)統(tǒng)調(diào)用最最常用來來作用于于設(shè)備, 內(nèi)核核能識(shí)別別幾個(gè)命命令. 注意這這些命令令, 當(dāng)當(dāng)用到你你的設(shè)備備時(shí), 在你自自己的文文件操作作被調(diào)用用之前被被解碼. 因此此, 如如果你選選擇相同同的號(hào)給給一個(gè)你你的 iiocttl命令令, 你你不會(huì)看看到任何何的給那那個(gè)命令令的請(qǐng)求求, 并并且應(yīng)用用程序獲獲得某些些不期望望的東西西, 因因?yàn)樵?iocctl 號(hào)之間間的沖突突.預(yù)定義命令令分為 3 類類:可對(duì)任何文文件發(fā)出出的(常常規(guī), 設(shè)備, FIIFO, 或者者 soockeet) 的那些些.只對(duì)常規(guī)文文件發(fā)出出的那些些.對(duì)文件系統(tǒng)統(tǒng)類型特特殊的那那些.最后一類的

27、的命令由由宿主文文件系統(tǒng)統(tǒng)的實(shí)現(xiàn)現(xiàn)來執(zhí)行行(這是是 chhatttr 命命令如何何工作的的). 設(shè)備驅(qū)驅(qū)動(dòng)編寫寫者只對(duì)對(duì)第一類類命令感感興趣, 它們們的魔數(shù)數(shù)是 T. 查看看其他類類的工作作留給讀讀者作為為練習(xí); exxt2_iocctl 是最有有趣的函函數(shù)(并并且比預(yù)預(yù)期的要要容易理理解), 因?yàn)闉樗鼘?shí)現(xiàn)現(xiàn) apppennd-oonlyy 標(biāo)志志和 iimmuutabble 標(biāo)志.下列 iooctll 命令令是預(yù)定定義給任任何文件件, 包包括設(shè)備備特殊的的文件:FIOCLLEX 設(shè)置 cllosee-onn-exxec 標(biāo)志( Cllosee onn EXXec). 設(shè)設(shè)置這個(gè)個(gè)標(biāo)志使使文件

28、描描述符被被關(guān)閉, 當(dāng)調(diào)調(diào)用進(jìn)程程執(zhí)行一一個(gè)新程程序時(shí).FIONCCLEXX 清除 cllosee-noo-exxec 標(biāo)志( Noot CCLosse oon EEXecc). 這個(gè)命命令恢復(fù)復(fù)普通文文件行為為, 復(fù)復(fù)原上面面 FIIOCLLEX 所做的的. FFIOAASYNNC 為為這個(gè)文文件設(shè)置置或者復(fù)復(fù)位異步步通知(如同在在本章中中異步步通知一節(jié)中中討論的的). 注意直直到 LLinuux 22.2.4 版版本的內(nèi)內(nèi)核不正正確地使使用這個(gè)個(gè)命令來來修改 O_SSYNCC 標(biāo)志志. 因因?yàn)閮蓚€(gè)個(gè)動(dòng)作都都可通過過 fccntll 來完完成, 沒有人人真正使使用 FFIOAASYNNC 命

29、命令, 它在這這里出現(xiàn)現(xiàn)只是為為了完整整性.FIOQSSIZEE 這個(gè)命令返返回一個(gè)個(gè)文件或或者目錄錄的大小小; 當(dāng)當(dāng)用作一一個(gè)設(shè)備備文件, 但是是, 它它返回一一個(gè) EENOTTTY 錯(cuò)誤.FIONBBIO Nonn-Bllockkingg I/O(在阻阻塞和非非阻塞操操作一一節(jié)中描描述). 這個(gè)個(gè)調(diào)用修修改在 fillp-f_fflaggs 中中的 OO_NOONBLLOCKK 標(biāo)志志. 給給這個(gè)系系統(tǒng)調(diào)用用的第 3 個(gè)個(gè)參數(shù)用用作指示示是否這這個(gè)標(biāo)志志被置位位或者清清除. (我們們將在本本章看到到這個(gè)標(biāo)標(biāo)志的角角色). 注意意常用的的改變這這個(gè)標(biāo)志志的方法法是使用用 fccntll 系統(tǒng)

30、統(tǒng)調(diào)用, 使用用 F_SETTFL 命令.列表中的最最后一項(xiàng)項(xiàng)介紹了了一個(gè)新新的系統(tǒng)統(tǒng)調(diào)用, fccntll, 它它看來象象 iooctll. 事事實(shí)上, fccntll 調(diào)用用非常類類似 iiocttl, 它也是是獲得一一個(gè)命令令參數(shù)和和一個(gè)額額外的(可選地地)參數(shù)數(shù). 它它保持和和 iooctll 獨(dú)立立主要是是因?yàn)闅v歷史原因因: 當(dāng)當(dāng) Unnix 開發(fā)者者面對(duì)控控制 II/O 操作的的問題時(shí)時(shí), 他他們決定定文件和和設(shè)備是是不同的的. 那那時(shí), 有 iiocttl 實(shí)實(shí)現(xiàn)的唯唯一設(shè)備備是 tttyss, 它它解釋了了為什么么 -EENOTTTY 是標(biāo)準(zhǔn)準(zhǔn)的對(duì)不不正確 iocctl 命令的

31、的回答. 事情情已經(jīng)改改變, 但是 fcnntl 保留為為一個(gè)獨(dú)獨(dú)立的系系統(tǒng)調(diào)用用.6.1.44.使用 iocctl 參數(shù)在看 scculll 驅(qū)動(dòng)動(dòng)的 iiocttl 代代碼之前前, 我我們需要要涉及的的另一點(diǎn)點(diǎn)是如何何使用這這個(gè)額外外的參數(shù)數(shù). 如如果它是是一個(gè)整整數(shù), 就容易易: 它它可以直直接使用用. 如如果它是是一個(gè)指指針, 但是, 必須須小心些些.當(dāng)用一個(gè)指指針引用用用戶空空間, 我們必必須確保保用戶地地址是有有效的. 試圖圖存取一一個(gè)沒驗(yàn)驗(yàn)證過的的用戶提提供的指指針可能能導(dǎo)致不不正確的的行為, 一個(gè)個(gè)內(nèi)核 oopps, 系統(tǒng)崩崩潰, 或者安安全問題題. 它它是驅(qū)動(dòng)動(dòng)的責(zé)任任來對(duì)每

32、每個(gè)它使使用的用用戶空間間地址進(jìn)進(jìn)行正確確的檢查查, 并并且返回回一個(gè)錯(cuò)錯(cuò)誤如果果它是無無效的.在第 3 章, 我們看看了 ccopyy_frrom_useer 和和 coopy_to_useer 函函數(shù), 它們可可用來安安全地移移動(dòng)數(shù)據(jù)據(jù)到和從從用戶空空間. 這些函函數(shù)也可可用在 iocctl 方法中中, 但但是 iiocttl 調(diào)調(diào)用常常常包含小小數(shù)據(jù)項(xiàng)項(xiàng), 可可通過其其他方法法更有效效地操作作. 開開始, 地址校校驗(yàn)(不不傳送數(shù)數(shù)據(jù))由由函數(shù) acccesss_okk 實(shí)現(xiàn)現(xiàn), 它它定義在在 :int aacceess_ok(intt tyype, coonstt vooid *addd

33、r, unnsiggnedd loong sizze); 第一個(gè)參數(shù)數(shù)應(yīng)當(dāng)是是 VEERIFFY_RREADD 或者者 VEERIFFY_WWRITTE, 依據(jù)這這個(gè)要進(jìn)進(jìn)行的動(dòng)動(dòng)作是否否是讀用用戶空間間內(nèi)存區(qū)區(qū)或者寫寫它. adddr 參參數(shù)持有有一個(gè)用用戶空間間地址, siize 是一個(gè)個(gè)字節(jié)量量. 例例如, 如果 iocctl 需要從從用戶空空間讀一一個(gè)整數(shù)數(shù), ssizee 是 sizzeoff(innt). 如果果你需要要讀和寫寫給定地地址, 使用 VERRIFYY_WRRITEE, 因因?yàn)樗鞘?VEERIRRY_RREADD 的超超集.不象大部分分的內(nèi)核核函數(shù), acccesss

34、_ook 返返回一個(gè)個(gè)布爾值值: 11 是成成功(存存取沒問問題)和和 0 是失敗敗(存取取有問題題). 如果它它返回假假, 驅(qū)驅(qū)動(dòng)應(yīng)當(dāng)當(dāng)返回 -EFFAULLT 給給調(diào)用者者.關(guān)于 acccesss_ook有多多個(gè)有趣趣的東西西要注意意. 首首先, 它不做做校驗(yàn)內(nèi)內(nèi)存存取取的完整整工作; 它只只檢查看看這個(gè)內(nèi)內(nèi)存引用用是在這這個(gè)進(jìn)程程有合理理權(quán)限的的內(nèi)存范范圍中. 特別別地, acccesss_okk 確保保這個(gè)地地址不指指向內(nèi)核核空間內(nèi)內(nèi)存. 第2, 大部部分驅(qū)動(dòng)動(dòng)代碼不不需要真真正調(diào)用用 acccesss_ook. 后面描描述的內(nèi)內(nèi)存存取取函數(shù)為為你負(fù)責(zé)責(zé)這個(gè). 但是是, 我我們來演演示

35、它的的使用, 以便便你可見見到它如如何完成成.sculll 源碼碼利用了了 ioocltt 號(hào)中中的位段段來檢查查參數(shù), 在 swiitchh 之前前:int eerr = 00, ttmp;int rretvval = 00;/* * exxtraact thee tyype andd nuumbeer bbitffiellds, annd ddont ddecoode * wrrongg cmmds: reeturrn EENOTTTY (innappproppriaate iocctl) beeforre aacceess_ok() */if (_IOCC_TYYPE(cmdd) !=

36、SSCULLL_IIOC_MAGGIC) retturnn -EENOTTTY;if (_IOCC_NRR(cmmd) SSCULLL_IIOC_MAXXNR) retturnn -EENOTTTY;/* * thhe ddireectiion is a bbitmmaskk, aand VERRIFYY_WRRITEE caatchhes R/WW * trranssferrs. Tyype iss usser-oriientted, whhilee * acccesss_ook iis kkernnel-oriientted, soo thhe cconcceptt off rreadd

37、aand * wwritte is revverssed */if (_IOCC_DIIR(ccmd) & _IOOC_RREADD) errr = !acccesss_ook(VVERIIFY_WRIITE, (vvoidd _useer *)arrg, _IOOC_SSIZEE(cmmd);else if (_IIOC_DIRR(cmmd) & _IOCC_WRRITEE) errr = !acccesss_ook(VVERIIFY_REAAD, (vooid _uuserr *)argg, _IOCC_SIIZE(cmdd);if (eerr) retturnn -EEFAUULT;在調(diào)

38、用 aacceess_ok 之后, 驅(qū)動(dòng)動(dòng)可安全全地進(jìn)行行真正的的傳輸. 加上上 coopy_froom_uuserr 和 coppy_tto_uuserr_ 函函數(shù), 程序員員可利用用一組為為被最多多使用的的數(shù)據(jù)大大小(11, 22, 44, 和和 8 字節(jié))而優(yōu)化化過的函函數(shù). 這些函函數(shù)在下下面列表表中描述述, 它它們定義義在 :put_uuserr(daatumm, pptr) _putt_usser(dattum, pttr) 這些宏定義義寫 ddatuum 到到用戶空空間; 它們相相對(duì)快, 并且且應(yīng)當(dāng)被被調(diào)用來來代替 coppy_tto_uuserr 無論論何時(shí)要要傳送單單個(gè)值時(shí)時(shí)

39、. 這這些宏已已被編寫寫來允許許傳遞任任何類型型的指針針到 pput_useer, 只要它它是一個(gè)個(gè)用戶空空間地址址. 傳傳送的數(shù)數(shù)據(jù)大小小依賴 prtt 參數(shù)數(shù)的類型型, 并并且在編編譯時(shí)使使用 ssizeeof 和 ttypeeof 等編譯譯器內(nèi)建建宏確定定. 結(jié)結(jié)果是, 如果果 prrt 是是一個(gè) chaar 指指針, 傳送一一個(gè)字節(jié)節(jié), 以以及對(duì)于于 2, 4, 和 可能的的 8 字節(jié).put_uuserr 檢查查來確保保這個(gè)進(jìn)進(jìn)程能夠夠?qū)懭虢o給定的內(nèi)內(nèi)存地址址. 它它在成功功時(shí)返回回 0, 并且且在錯(cuò)誤誤時(shí)返回回 -EEFAUULT. _putt_usser 進(jìn)行更更少的檢檢查(它它

40、不調(diào)用用 acccesss_ook), 但是是仍然能能夠失敗敗如果被被指向的的內(nèi)存對(duì)對(duì)用戶是是不可寫寫的. 因此, _putt_usser 應(yīng)當(dāng)只只用在內(nèi)內(nèi)存區(qū)已已經(jīng)用 acccesss_okk 檢查查過的時(shí)時(shí)候.作為一個(gè)通通用的規(guī)規(guī)則, 當(dāng)你實(shí)實(shí)現(xiàn)一個(gè)個(gè) reead 方法時(shí)時(shí), 調(diào)調(diào)用 _puut_uuserr 來節(jié)節(jié)省幾個(gè)個(gè)周期, 或者者當(dāng)你拷拷貝幾個(gè)個(gè)項(xiàng)時(shí), 因此此, 在在第一次次數(shù)據(jù)傳傳送之前前調(diào)用 acccesss_okk 一次次, 如如同上面面 iooctll 所示示.get_uuserr(loocall, pptr) _gett_usser(loccal, pttr) 這些宏定義

41、義用來從從用戶空空間接收收單個(gè)數(shù)數(shù)據(jù). 它們象象 puut_uuserr 和 _pput_useer, 但是在在相反方方向傳遞遞數(shù)據(jù). 獲取取的值存存儲(chǔ)于本本地變量量 loocall; 返返回值指指出這個(gè)個(gè)操作是是否成功功. 再再次, _gget_useer 應(yīng)應(yīng)當(dāng)只用用在已經(jīng)經(jīng)使用 acccesss_okk 校驗(yàn)驗(yàn)過的地地址.如果做一個(gè)個(gè)嘗試來來使用一一個(gè)列出出的函數(shù)數(shù)來傳送送一個(gè)不不適合特特定大小小的值, 結(jié)果果常常是是一個(gè)來來自編譯譯器的奇奇怪消息息, 例例如ccoveersiion to nonn-sccalaar ttypee reequeesteed. 在這這些情況況中, 必須使使

42、用 ccopyy_too_usser 或者 coppy_ffromm_usser.6.1.55.兼容性性和受限限操作存取一個(gè)設(shè)設(shè)備由設(shè)設(shè)備文件件上的許許可權(quán)控控制, 并且驅(qū)驅(qū)動(dòng)正常常地不涉涉及到許許可權(quán)的的檢查. 但是是, 有有些情形形, 在在保證給給任何用用戶對(duì)設(shè)設(shè)備的讀讀寫許可可的地方方, 一一些控制制操作仍仍然應(yīng)當(dāng)當(dāng)被拒絕絕. 例例如, 不是所所有的磁磁帶驅(qū)動(dòng)動(dòng)器的用用戶都應(yīng)應(yīng)當(dāng)能夠夠設(shè)置它它的缺省省塊大小小, 并并且一個(gè)個(gè)已經(jīng)被被給予對(duì)對(duì)一個(gè)磁磁盤設(shè)備備讀寫權(quán)權(quán)限的用用戶應(yīng)當(dāng)當(dāng)仍然可可能被拒拒絕來格格式化它它. 在在這樣的的情況下下, 驅(qū)驅(qū)動(dòng)必須須進(jìn)行額額外的檢檢查來確確保用戶戶能夠進(jìn)

43、進(jìn)行被請(qǐng)請(qǐng)求的操操作.傳統(tǒng)上 uunixx 系統(tǒng)統(tǒng)對(duì)超級(jí)級(jí)用戶帳帳戶限制制了特權(quán)權(quán)操作. 這意意味著特特權(quán)是一一個(gè)全有有-或-全無的的東西 - 超級(jí)用用戶可能能任意做做任何事事情, 但是所所有其他他的用戶戶被高度度限制了了. LLinuux 內(nèi)內(nèi)核提供供了一個(gè)個(gè)更加靈靈活的系系統(tǒng), 稱為能能力. 一個(gè)基基于能力力的系統(tǒng)統(tǒng)丟棄了了全有-或全無無模式, 并且且打破特特權(quán)操作作為獨(dú)立立的子類類. 這這種方式式, 一一個(gè)特殊殊的用戶戶(或者者是程序序)可被被授權(quán)來來進(jìn)行一一個(gè)特定定的特權(quán)權(quán)操作而而不必泄泄漏進(jìn)行行其他的的, 無無關(guān)的操操作的能能力. 內(nèi)核在在許可權(quán)權(quán)管理上上排他地地使用能能力, 并且輸

44、輸出 22 個(gè)系系統(tǒng)調(diào)用用 caapgeet 和和 caapseet, 來允許許它們被被從用戶戶空間管管理.全部能力可可在 中中找到. 這些些是對(duì)系系統(tǒng)唯一一可用的的能力; 對(duì)于于驅(qū)動(dòng)作作者或者者系統(tǒng)管管理員, 不可可能不修修改內(nèi)核核源碼而而來定義義新的. 設(shè)備備驅(qū)動(dòng)編編寫者可可能感興興趣的這這些能力力的一個(gè)個(gè)子集, 包括括下面:CAP_DDAC_OVEERRIIDE 這個(gè)能力來來推翻在在文件和和目錄上上的存取取的限制制(數(shù)據(jù)據(jù)存取控控制, 或者 DACC).CAP_NNET_ADMMIN 進(jìn)行網(wǎng)絡(luò)管管理任務(wù)務(wù)的能力力, 包包括那些些能夠影影響網(wǎng)絡(luò)絡(luò)接口的的.CAP_SSYS_MODDULEE

45、 加載或去除除內(nèi)核模模塊的能能力.CAP_SSYS_RAWWIO 進(jìn)行 rraw I/O 操操作的能能力. 例子包包括存取取設(shè)備端端口或者者直接和和 USSB 設(shè)設(shè)備通訊訊.CAP_SSYS_ADMMIN 一個(gè)捕獲-全部的的能力, 提供供對(duì)許多多系統(tǒng)管管理操作作的存取取.CAP_SSYS_TTYY_COONFIIG 進(jìn)行 ttty 配配置任務(wù)務(wù)的能力力.在進(jìn)行一個(gè)個(gè)特權(quán)操操作之前前, 一一個(gè)設(shè)備備驅(qū)動(dòng)應(yīng)應(yīng)當(dāng)檢查查調(diào)用進(jìn)進(jìn)程有合合適的能能力; 不這樣樣做可能能導(dǎo)致用用戶進(jìn)程程進(jìn)行非非法的操操作, 對(duì)系統(tǒng)統(tǒng)的穩(wěn)定定和安全全有壞的的后果. 能力力檢查是是通過 cappablle 函函數(shù)來進(jìn)進(jìn)行的(定

46、義在在 ): int cappablle(iint cappabiilitty); 在 scuull 例子驅(qū)驅(qū)動(dòng)中, 任何何用戶被被許可來來查詢 quaantuum 和和 quuanttum 集的大大小. 只有特特權(quán)用戶戶, 但但是, 可改變變這些值值, 因因?yàn)椴贿m適當(dāng)?shù)闹抵悼赡芎芎軌牡赜坝绊懴到y(tǒng)統(tǒng)性能. 當(dāng)需需要時(shí), iooctll 的 scuull 實(shí)現(xiàn)檢檢查用戶戶的特權(quán)權(quán)級(jí)別, 如下下: if (! ccapaablee (CCAP_SYSS_ADDMINN) retuurn -EPPERMM;在這個(gè)任務(wù)務(wù)缺乏一一個(gè)更加加特定的的能力時(shí)時(shí), CCAP_SYSS_ADDMINN 被選選擇來

47、做做這個(gè)測測試.6.1.66.iocctl 命令的的實(shí)現(xiàn)ioctll 的 scuull 實(shí)現(xiàn)只只傳遞設(shè)設(shè)備的配配置參數(shù)數(shù), 并并且象下下面這樣樣容易:switcch(ccmd)case SCUULL_IOCCRESSET: scuull_quaantuum = SCCULLL_QUUANTTUM; scuull_qseet = SCCULLL_QSSET; breeak;case SCUULL_IOCCSQUUANTTUM: /* Seet: argg poointts tto tthe vallue */ if (! cappablle (CAPP_SYYS_AADMIIN) rretuur

48、n -EPPERMM; rettvall = _gget_useer(ssculll_qquanntumm, (intt _useer *)arrg); breeak;case SCUULL_IOCCTQUUANTTUM: /* Teell: arrg iis tthe vallue */ if (! cappablle (CAPP_SYYS_AADMIIN) rretuurn -EPPERMM; scuull_quaantuum = arrg; breeak;case SCUULL_IOCCGQUUANTTUM: /* Geet: argg iss poointter to ressultt

49、 */ rettvall = _pput_useer(ssculll_qquanntumm, (intt _useer *)arrg); breeak;case SCUULL_IOCCQQUUANTTUM: /* Quueryy: rretuurn it (itts possitiive) */ retturnn scculll_quuanttum;case SCUULL_IOCCXQUUANTTUM: /* eXXchaangee: uuse argg ass poointter */ if (! cappablle (CAPP_SYYS_AADMIIN) rretuurn -EPPERMM

50、; tmpp = scuull_quaantuum; rettvall = _gget_useer(ssculll_qquanntumm, (intt _useer *)arrg); if (reetvaal = 00) rretvval = _puut_uuserr(tmmp, (innt _usser *)aarg); breeak;case SCUULL_IOCCHQUUANTTUM: /* sHHiftt: llikee Teell + QQuerry */ if (! cappablle (CAPP_SYYS_AADMIIN) rretuurn -EPPERMM; tmpp = sc

51、uull_quaantuum; scuull_quaantuum = arrg; retturnn tmmp;defauult: /* reedunndannt, as cmdd waas cchecckedd aggainnst MAXXNR */ retturnn -EENOTTTY;returrn rretvval;sculll 還包包含 66 個(gè)入入口項(xiàng)作作用于 scuull_qseet. 這些入入口項(xiàng)和和給 ssculll_qquanntumm 的是是一致的的, 并并且不值值得展示示出來.從調(diào)用者的的觀點(diǎn)看看(即從從用戶空空間), 這 6 種種傳遞和和接收參參數(shù)的方方法看來來如下:i

52、nt qquanntumm;ioctll(fdd,SCCULLL_IOOCSQQUANNTUMM, &quaantuum); /* SSet by poiinteer */ioctll(fdd,SCCULLL_IOOCTQQUANNTUMM, qquanntumm); /* Seet bby vvaluue */ioctll(fdd,SCCULLL_IOOCGQQUANNTUMM, &quaantuum); /* GGet by poiinteer */quanttum = iiocttl(ffd,SSCULLL_IIOCQQQUAANTUUM); /* GGet by retturnn va

53、aluee */ioctll(fdd,SCCULLL_IOOCXQQUANNTUMM, &quaantuum); /* EExchhangge bby ppoinnterr */quanttum = iiocttl(ffd,SSCULLL_IIOCHHQUAANTUUM, quaantuum); /* Exxchaangee byy vaaluee */當(dāng)然, 一一個(gè)正常常的驅(qū)動(dòng)動(dòng)不可能能實(shí)現(xiàn)這這樣一個(gè)個(gè)調(diào)用模模式的混混合體. 我們們這里這這樣做只只是為了了演示做做事情的的不同方方式. 但是, 正常常地, 數(shù)據(jù)交交換將一一致地進(jìn)進(jìn)行, 通過指指針或者者通過值值, 并并且要避避免混合合這 22

54、種技技術(shù).6.1.77.不用 iocctl 的設(shè)備備控制有時(shí)控制設(shè)設(shè)備最好好是通過過寫控制制序列到到設(shè)備自自身來實(shí)實(shí)現(xiàn). 例如, 這個(gè)個(gè)技術(shù)用用在控制制臺(tái)驅(qū)動(dòng)動(dòng)中, 這里所所謂的 esccapee 序列列被用來來移動(dòng)光光標(biāo), 改變?nèi)比笔〉念侇伾? 或者進(jìn)進(jìn)行其他他的配置置任務(wù). 這樣樣實(shí)現(xiàn)設(shè)設(shè)備控制制的好處處是用戶戶可僅僅僅通過寫寫數(shù)據(jù)控控制設(shè)備備, 不不必使用用(或者者有時(shí)候候?qū)?只只為配置置設(shè)備而而建立的的程序. 當(dāng)設(shè)設(shè)備可這這樣來控控制, 發(fā)出命命令的程程序甚至至常常不不需要運(yùn)運(yùn)行在和和它要控控制的設(shè)設(shè)備所在在的同一一個(gè)系統(tǒng)統(tǒng)上.例如, ssetttermm 程序序作用于于控制臺(tái)臺(tái)(或者

55、者其他終終端)配配置, 通過打打印 eescaape 序列. 控制制程序可可位于和和被控制制的設(shè)備備不同的的一臺(tái)計(jì)計(jì)算機(jī)上上, 因因?yàn)橐粋€(gè)個(gè)簡單的的數(shù)據(jù)流流重定向向可完成成這個(gè)配配置工作作. 這這是每次次你運(yùn)行行一個(gè)遠(yuǎn)遠(yuǎn)程 ttty 會(huì)話時(shí)時(shí)所發(fā)生生的事情情: eescaape 序列在在遠(yuǎn)端被被打印但但是影響響到本地地的 ttty; 然而而, 這這個(gè)技術(shù)術(shù)不局限限于 tttyss.通過打印來來控制的的缺點(diǎn)是是它給設(shè)設(shè)備增加加了策略略限制; 例如如, 它它僅僅當(dāng)當(dāng)你確信信在正常常操作時(shí)時(shí)控制序序列不會(huì)會(huì)出現(xiàn)在在正被寫寫入設(shè)備備的數(shù)據(jù)據(jù)中. 這對(duì)于于 tttys 只是部部分正確確的. 盡管一一個(gè)文

56、本本顯示意意味著只只顯示 ASCCII 字符, 有時(shí)時(shí)控制字字符可潛潛入正被被寫入的的數(shù)據(jù)中中, 并并且可能能, 因因此, 影響控控制臺(tái)的的配置. 例如如, 這這可能發(fā)發(fā)生在你你顯示一一個(gè)二進(jìn)進(jìn)制文件件到屏幕幕時(shí); 產(chǎn)生的的亂碼可可能包含含任何東東西, 并且最最后你常常常在你你的控制制臺(tái)上出出現(xiàn)錯(cuò)誤誤的字體體.通過寫來控控制是當(dāng)當(dāng)然的使使用方法法了, 對(duì)于不不用傳送送數(shù)據(jù)而而只是響響應(yīng)命令令的設(shè)備備, 例例如遙控控設(shè)備.例如, 被被你們作作者當(dāng)中中的一個(gè)個(gè)編寫來來好玩的的驅(qū)動(dòng), 移動(dòng)動(dòng)一個(gè) 2 軸軸上的攝攝像機(jī). 在這這個(gè)驅(qū)動(dòng)動(dòng)里, 這個(gè)設(shè)備是一對(duì)對(duì)老式步步進(jìn)電機(jī)機(jī), 它它們不能能真正讀讀或?qū)?/p>

57、. 給一一個(gè)步進(jìn)進(jìn)電機(jī)發(fā)送數(shù)數(shù)據(jù)流的概念念沒有任任何意義義. 在在這個(gè)情情況下, 驅(qū)動(dòng)動(dòng)解釋正正被寫入入的數(shù)據(jù)據(jù)作為 ASCCII 命令并并且轉(zhuǎn)換換這個(gè)請(qǐng)請(qǐng)求為脈脈沖序列列, 來來操縱步步進(jìn)電機(jī)機(jī). 這這個(gè)概念念類似于于, 有有些, 你發(fā)給給貓的 AT 命令來來建立通通訊, 主要的的不同是是和貓通通訊的串串口必須須也傳送送真正的的數(shù)據(jù). 直接接設(shè)備控控制的好好處是你你可以使使用 ccat 來移動(dòng)動(dòng)攝像機(jī)機(jī), 而而不必寫寫和編譯譯特殊的的代碼來來發(fā)出 iocctl 調(diào)用.當(dāng)編寫面向向命令的的驅(qū)動(dòng), 沒有有理由實(shí)實(shí)現(xiàn) iiocttl 命命令. 一個(gè)解解釋器中中的額外外命令更更容易實(shí)實(shí)現(xiàn)并使使用.有

58、時(shí), 然然而, 你可能能選擇使使用其他他的方法法:不必必轉(zhuǎn)變 wriite 方法為為一個(gè)解解釋器和和避免 iocctl, 你可可能選擇擇完全避避免寫并并且專門門使用 iocctl 命令, 而實(shí)實(shí)現(xiàn)驅(qū)動(dòng)動(dòng)為使用用一個(gè)特特殊的命命令行工工具來發(fā)發(fā)送這些些命令到到驅(qū)動(dòng). 這個(gè)個(gè)方法轉(zhuǎn)轉(zhuǎn)移復(fù)雜雜性從內(nèi)內(nèi)核空間間到用戶戶空間, 這里里可能更更易處理理, 并并且?guī)椭3烛?qū)驅(qū)動(dòng)小, 而拒拒絕使用用簡單的的 caat 或或者 eechoo 命令令. 但是是, 這這個(gè)文件件的維護(hù)護(hù)在后來來有些少少見了. 實(shí)際際上, 所有的的當(dāng)前使使用的 libbc 實(shí)實(shí)現(xiàn)(包包括 uuCliibc) 僅將將 -440955

59、到 -1 的值當(dāng)當(dāng)作錯(cuò)誤誤碼. 不幸的的是, 能夠返返回大的的負(fù)數(shù)而而不是小小的, 沒有多多大用處處.6.2.阻塞 I/OO回顧第 33 章, 我們們看到如如何實(shí)現(xiàn)現(xiàn) reead 和 wwritte 方方法. 在此, 但是是, 我我們跳過過了一個(gè)個(gè)重要的的問題:一個(gè)驅(qū)驅(qū)動(dòng)當(dāng)它它無法立立刻滿足足請(qǐng)求應(yīng)應(yīng)當(dāng)如何何響應(yīng)? 一個(gè)個(gè)對(duì) rreadd 的調(diào)調(diào)用可能能當(dāng)沒有有數(shù)據(jù)時(shí)時(shí)到來, 而以以后會(huì)期期待更多多的數(shù)據(jù)據(jù). 或或者一個(gè)個(gè)進(jìn)程可可能試圖圖寫, 但是你你的設(shè)備備沒有準(zhǔn)準(zhǔn)備好接接受數(shù)據(jù)據(jù), 因因?yàn)槟愕牡妮敵鼍従彌_滿了了. 調(diào)調(diào)用進(jìn)程程往往不不關(guān)心這這種問題題; 程程序員只只希望調(diào)調(diào)用 rreadd

60、 或 wriite 并且使使調(diào)用返返回, 在必要要的工作作已完成成后. 這樣, 在這這樣的情情形中, 你的的驅(qū)動(dòng)應(yīng)應(yīng)當(dāng)(缺缺省地)阻塞進(jìn)進(jìn)程, 使它進(jìn)進(jìn)入睡眠眠直到請(qǐng)請(qǐng)求可繼繼續(xù). 本節(jié)展示如如何使一一個(gè)進(jìn)程程睡眠并并且之后后再次喚喚醒它. 如常常, 但但是, 我們必必須首先先解釋幾幾個(gè)概念念.6.2.11.睡眠的的介紹對(duì)于一個(gè)進(jìn)進(jìn)程睡睡眠意意味著什什么? 當(dāng)一個(gè)個(gè)進(jìn)程被被置為睡睡眠, 它被標(biāo)標(biāo)識(shí)為處處于一個(gè)個(gè)特殊的的狀態(tài)并并且從調(diào)調(diào)度器的的運(yùn)行隊(duì)隊(duì)列中去去除. 直到發(fā)發(fā)生某些些事情改改變了那那個(gè)狀態(tài)態(tài), 這這個(gè)進(jìn)程程將不被被在任何何 CPPU 上上調(diào)度, 并且且, 因因此, 將不會(huì)會(huì)運(yùn)行.

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論