高級字符驅動操作說明_第1頁
高級字符驅動操作說明_第2頁
高級字符驅動操作說明_第3頁
高級字符驅動操作說明_第4頁
高級字符驅動操作說明_第5頁
已閱讀5頁,還剩79頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、 HYPERLINK 更多企業(yè)業(yè)學院:中小企企業(yè)管理理全能版版183套套講座+897700份份資料總經(jīng)理理、高層層管理49套講講座+1163888份資料中層管管理學院院46套講講座+660200份資料國學智智慧、易易經(jīng)46套講講座人力資資源學院院56套講講座+2271223份資料各階段段員工培培訓學院院77套講講座+ 3244份資料員工管管理企業(yè)業(yè)學院67套講講座+ 87220份資料工廠生生產管理理學院52套講講座+ 139920份份資料財務管管理學院院53套講講座+ 179945份份資料銷售經(jīng)經(jīng)理學院院56套講講座+ 143350份份資料銷售人人員培訓訓學院72套講講座+ 48779份資料(

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

3、各種和和用戶空空間同步步的方法法; 在在本章結結尾, 你有一一個充分分的認識識對于如如何使進進程睡眠眠(并且且喚醒它它們), 實現(xiàn)現(xiàn)非阻塞塞的 II/O, 并且且通知用用戶空間間當你的的設備可可用來讀讀或寫. 我們們以查看看如何在在驅動中中實現(xiàn)幾幾個不同同的設備備存取策策略來結結束.這里討論論的概念念通過 scuull 驅動的的幾個修修改版本本來演示示. 再再一次, 所有有的都使使用內存存中的虛虛擬設備備來實現(xiàn)現(xiàn), 因因此你可可自己試試驗這些些代碼而而不必使使用任何何特別的的硬件. 到此此為止, 你可可能在想想親手使使用真正正的硬件件, 但但是那將將必須等等到第 9 章章.6.1.iocctl

4、 接口大部分驅驅動需要要 - 除了了讀寫設設備的能能力 - 通通過設備備驅動進進行各種種硬件控控制的能能力. 大部分分設備可可進行超超出簡單單的數(shù)據(jù)據(jù)傳輸之之外的操操作; 用戶空空間必須須常常能能夠請求求, 例例如, 設備鎖鎖上它的的門, 彈出它它的介質質, 報報告錯誤誤信息, 改變變波特率率, 或或者自我我銷毀. 這些些操作常常常通過過 iooctll 方法法來支持持, 它它通過相相同名子子的系統(tǒng)統(tǒng)調用來來實現(xiàn).在用戶空空間, iocctl 系統(tǒng)調調用有下下面的原原型:int iocctl(intt fdd, uunsiigneed llongg cmmd, .); 這個原型型由于這這些點而

5、而凸現(xiàn)于于 Unnix 系統(tǒng)調調用列表表, 這這些點常常常表示示函數(shù)有有數(shù)目不不定的參參數(shù). 在實際際系統(tǒng)中中, 但但是, 一個系系統(tǒng)調用用不能真真正有變變數(shù)目的的參數(shù). 系統(tǒng)統(tǒng)調用必必須有一一個很好好定義的的原型, 因為為用戶程程序可存存取它們們只能通通過硬件件的門門. 因此, 原型型中的點點不表示示一個變變數(shù)目的的參數(shù), 而是是一個單單個可選選的參數(shù)數(shù), 傳傳統(tǒng)上標標識為 chaar *arggp. 這些點點在那里里只是為為了阻止止在編譯譯時的類類型檢查查. 第第 3 個參數(shù)數(shù)的實際際特點依依賴所發(fā)發(fā)出的特特定的控控制命令令( 第第 2 個參數(shù)數(shù) ). 一些些命令不不用參數(shù)數(shù), 一一些用一

6、一個整數(shù)數(shù)值, 以及一一些使用用指向其其他數(shù)據(jù)據(jù)的指針針. 使使用一個個指針是是傳遞任任意數(shù)據(jù)據(jù)到 iiocttl 調調用的方方法; 設備接接著可與與用戶空空間交換換任何數(shù)數(shù)量的數(shù)數(shù)據(jù).iocttl 調調用的非非結構化化特性使使它在內內核開發(fā)發(fā)者中失失寵. 每個 iocctl 命令, 基本本上, 是一個個單獨的的, 常常常無文文檔的系系統(tǒng)調用用, 并并且沒有有方法以以任何類類型的全全面的方方式核查查這些調調用. 也難于于使非結結構化的的 iooctll 參數(shù)數(shù)在所有有系統(tǒng)上上一致工工作; 例如, 考慮慮運行在在 322-位模模式的一一個用戶戶進程的的 644-位 系統(tǒng). 結果果, 有有很大的的

7、壓力來來實現(xiàn)混混雜的控控制操作作, 只只通過任任何其他他的方法法. 可可能的選選擇包括括嵌入命命令到數(shù)數(shù)據(jù)流(本章稍稍后我們們將討論論這個方方法)或或者使用用虛擬文文件系統(tǒng)統(tǒng), 要要么是 syssfs 要么是是設備特特定的文文件系統(tǒng)統(tǒng). (我們將將在 114 章章看看 syssfs). 但但是, 事實是是 iooctll 常常常是最容容易的和和最直接接的選擇擇,對于于真正的的設備操操作.iocttl 驅驅動方法法有和用用戶空間間版本不不同的原原型:int (*iiocttl) (sttrucct iinodde *inoode, sttrucct ffilee *ffilpp, uunsiig

8、need iint cmdd, uunsiigneed llongg arrg);inodde 和和 fiilp 指針是是對應應應用程序序傳遞的的文件描描述符 fd 的值, 和傳傳遞給 opeen 方方法的相相同參數(shù)數(shù). ccmd 參數(shù)從從用戶那那里不改改變地傳傳下來, 并且且可選的的參數(shù) argg 參數(shù)數(shù)以一個個 unnsiggnedd loong 的形式式傳遞, 不管管它是否否由用戶戶給定為為一個整整數(shù)或一一個指針針. 如如果調用用程序不不傳遞第第 3 個參數(shù)數(shù), 被被驅動操操作收到到的 aarg 值是無無定義的的. 因因為類型型檢查在在這個額額外參數(shù)數(shù)上被關關閉, 編譯器器不能警警告你如

9、如果一個個無效的的參數(shù)被被傳遞給給 iooctll, 并并且任何何關聯(lián)的的錯誤將將難以查查找.如果你可可能想到到的, 大部分分 iooctll 實現(xiàn)現(xiàn)包括一一個大的的 swwitcch 語語句來根根據(jù) ccmd 參數(shù), 選擇擇正確的的做法. 不同同的命令令有不同同的數(shù)值值, 它它們常常常被給予予符號名名來簡化化編碼. 符號號名通過過一個預預處理定定義來安安排. 定制的的驅動常常常聲明明這樣的的符號在在它們的的頭文件件中; scuull.h 為為 scculll 聲明明它們. 用戶戶程序必必須, 當然, 包含含那個頭頭文件來來存取這這些符號號.6.1.1.選擇 iocctl 命令在為 iioct

10、tl 編編寫代碼碼之前, 你需需要選擇擇對應命命令的數(shù)數(shù)字. 許多程程序員的的第一個個本能的的反應是是選擇一一組小數(shù)數(shù)從0或或1開始始, 并并且從此此開始向向上. 但是, 有充充分的理理由不這這樣做. iooctll 命令令數(shù)字應應當在這這個系統(tǒng)統(tǒng)是唯一一的, 為了阻阻止向錯錯誤的設設備發(fā)出出正確的的命令而而引起的的錯誤. 這樣樣的不匹匹配不會會不可能能發(fā)生, 并且且一個程程序可能能發(fā)現(xiàn)它它自己試試圖改變變一個非非串口輸輸入系統(tǒng)統(tǒng)的波特特率, 例如一一個 FFIFOO 或者者一個音音頻設備備. 如如果這樣樣的 iiocttl 號號是唯一一的, 這個應應用程序序得到一一個 EEINVVAL 錯誤

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

12、為你你的驅動動選擇 iocctl 號, 你應當當首先檢檢查 iinclludee/assm/iiocttl.hh 和 Doccumeentaatioon/iiocttl-nnumbber.txtt. 這這個頭文文件定義義你將使使用的位位段: typpe(魔魔數(shù)), 序號號, 傳傳輸方向向, 和和參數(shù)大大小. iocctl-nummberr.txxt 文文件列舉舉了在內內核中使使用的魔魔數(shù), 因因此你將將可選擇擇你自己己的魔數(shù)數(shù)并且避避免交疊疊. 這這個文本本文件也也列舉了了為什么么應當使使用慣例例的原因因.定義 iiocttl 命命令號的的正確方方法使用用 4 個位段段, 它它們有下下列的含含

13、義. 這個列列表中介介紹的新新符號定定義在 .typee 魔數(shù). 只是選選擇一個個數(shù)(在在參考了了 iooctll-nuumbeer.ttxt之之后)并并且使用用它在整整個驅動動中. 這個成成員是 8 位位寬(_IOCC_TYYPEBBITSS). numbber 序(順序序)號. 它是是 8 位(_IOCC_NRRBITTS)寬寬. direectiion 數(shù)據(jù)傳送送的方向向,如果果這個特特殊的命命令涉及及數(shù)據(jù)傳傳送. 可能的的值是 _IOOC_NNONEE(沒有有數(shù)據(jù)傳傳輸), _IIOC_REAAD, _IOOC_WWRITTE, 和 _IOCC_REEAD|_IOOC_WWRITTE

14、(數(shù)據(jù)在在2個方方向被傳傳送). 數(shù)據(jù)據(jù)傳送是是從應用用程序的的觀點來來看待的的; _IOCC_REEAD 意思是是從設備備讀, 因此設設備必須須寫到用用戶空間間. 注注意這個個成員是是一個位位掩碼, 因此此 _IIOC_REAAD 和和 _IIOC_WRIITE 可使用用一個邏邏輯 AAND 操作來來抽取.sizee 涉及到的的用戶數(shù)數(shù)據(jù)的大大小. 這個成成員的寬寬度是依依賴體系系的, 但是常常常是 13 或者 14 位. 你可為為你的特特定體系系在宏 _IOOC_SSIZEEBITTS 中中找到它它的值. 你使使用這個個 siize 成員不不是強制制的 - 內核核不檢查查它 - 但但是它是

15、是一個好好主意. 正確確使用這這個成員員可幫助助檢測用用戶空間間程序的的錯誤并并使你實實現(xiàn)向后后兼容, 如果果你曾需需要改變變相關數(shù)數(shù)據(jù)項的的大小. 如果果你需要要更大的的數(shù)據(jù)結結構, 但是, 你可可忽略這這個 ssizee 成員員. 我我們很快快見到如如何使用用這個成成員.頭文件 , 它包含含在 中, 定義宏宏來幫助助建立命命令號, 如下下: _IO(typpe,nnr)(給沒有有參數(shù)的的命令), _IORR(tyype, nrre, dattatyype)(給從從驅動中中讀數(shù)據(jù)據(jù)的), _IIOW(typpe,nnr,ddataatyppe)(給寫數(shù)數(shù)據(jù)), 和 _IOOWR(typpe,

16、nnr,ddataatyppe)(給雙向向傳送). ttypee 和 nummberr 成員員作為參參數(shù)被傳傳遞, 并且 sizze 成成員通過過應用 sizzeoff 到 dattatyype 參數(shù)而而得到.這個頭文文件還定定義宏, 可被被用在你你的驅動動中來解解碼這個個號: _IOOC_DDIR(nr), _IOCC_TYYPE(nr), _IOCC_NRR(nrr), 和 _IOCC_SIIZE(nr). 我我們不進進入任何何這些宏宏的細節(jié)節(jié), 因因為頭文文件是清清楚的, 并且且在本節(jié)節(jié)稍后有有例子代代碼展示示.這里是一一些 iiocttl 命命令如何何在 ssculll 被被定義的的.

17、 特特別地, 這些些命令設設置和獲獲得驅動動的可配配置參數(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真正的源源文件定定義幾個個額外的的這里沒沒有出現(xiàn)現(xiàn)的命令令.我們選擇擇實現(xiàn) 2 種種方法傳傳遞整數(shù)數(shù)參數(shù): 通過過指針和和通過明明確的值值(盡管管, 由由于一個個已存在在的慣例例, iiocllt 應應當通過過指針交交換值). 類類似地,

22、 2 種方法法被用來來返回一一個整數(shù)數(shù)值:通通過指針針和通過過設置返返回值. 這個個有效只只要返回回值是一一個正的的整數(shù); 如同同你現(xiàn)在在所知道道的, 在從任任何系統(tǒng)統(tǒng)調用返返回時, 一個個正值被被保留(如同我我們在 reaad 和和 wrritee 中見見到的), 而而一個負負值被看看作一個個錯誤并并且被用用來在用用戶空間間設置 errrno.excchannge和sshifft操操作對于于 scculll 沒有有特別的的用處. 我們們實現(xiàn)excchannge來顯示示驅動如如何結合合獨立的的操作到到單個的的原子的的操作, 并且且shhiftt來連連接ttelll和queery. 有有時需要要

23、象這樣樣的原子子的測試試-和-設置操操作, 特別地地, 當當應用程程序需要要設置和和釋放鎖鎖.命令的明明確的序序號沒有有特別的的含義. 它只只用來區(qū)區(qū)分命令令. 實實際上, 你甚甚至可使使用相同同的序號號給一個個讀命令令和一個個寫命令令, 因因為實際際的 iiocttl 號號在方方向位位是不同同的, 但是你你沒有理理由這樣樣做. 我們選選擇在任任何地方方不使用用命令的的序號除除了聲明明中, 因此我我們不分分配一個個返回值值給它. 這就就是為什什么明確確的號出出現(xiàn)在之之前給定定的定義義中. 這個例例子展示示了一個個使用命命令號的的方法, 但是是你有自自由不這這樣做.除了少數(shù)數(shù)幾個預預定義的的命令

24、(馬上就就討論), iiocttl 的的 cmmd 參參數(shù)的值值當前不不被內核核使用, 并且且在將來來也很不不可能. 因此此, 你你可以, 如果果你覺得得懶, 避免前前面展示示的復雜雜的聲明明并明確確聲明一一組調整整數(shù)字. 另一一方面, 如果果你做了了, 你你不會從從使用這這些位段段中獲益益, 并并且你會會遇到困困難如果果你曾提提交你的的代碼來來包含在在主線內內核中. 頭文文件 是是這個老老式方法法的例子子, 使使用 116-位位的調整整值來定定義 iiocttl 命命令. 那個源源代碼依依靠調整整數(shù)因為為使用那那個時候候遵循的的慣例, 不是是由于懶懶惰. 現(xiàn)在改改變它可可能導致致無理由由的不

25、兼兼容.6.1.2.返回值值iocttl 的的實現(xiàn)常常常是一一個 sswittch 語句, 基于于命令號號. 但但是當命命令號沒沒有匹配配一個有有效的操操作時缺缺省的選選擇應當當是什么么? 這這個問題題是有爭爭議的. 幾個個內核函函數(shù)返回回 -EENIVVAL(Innvallid arggumeent), 它有意意義是因因為命令令參數(shù)確確實不是是一個有有效的. POOSIXX 標準準, 但但是, 說如果果一個不不合適的的 iooctll 命令令被發(fā)出出, 那那么 -ENOOTTYY 應當當被返回回. 這這個錯誤誤碼被 C 庫庫解釋為為設備備的不適適當?shù)?iocctl, 這這常常正正是程序序員需

26、要要聽到的的. 然然而, 它仍然然是相當當普遍的的來返回回 -EEINVVAL, 對于于響應一一個無效效的 iiocttl 命命令.6.1.3.預定義義的命令令盡管 iiocttl 系系統(tǒng)調用用最常用用來作用用于設備備, 內內核能識識別幾個個命令. 注意意這些命命令, 當用到到你的設設備時, 在你你自己的的文件操操作被調調用之前前被解碼碼. 因因此, 如果你你選擇相相同的號號給一個個你的 iocctl命命令, 你不會會看到任任何的給給那個命命令的請請求, 并且應應用程序序獲得某某些不期期望的東東西, 因為在在 iooctll 號之之間的沖沖突.預定義命命令分為為 3 類:可對任何何文件發(fā)發(fā)出的

27、(常規(guī), 設備備, FFIFOO, 或或者 ssockket) 的那那些.只對常規(guī)規(guī)文件發(fā)發(fā)出的那那些.對文件系系統(tǒng)類型型特殊的的那些.最后一類類的命令令由宿主主文件系系統(tǒng)的實實現(xiàn)來執(zhí)執(zhí)行(這這是 cchatttr 命令如如何工作作的). 設備備驅動編編寫者只只對第一一類命令令感興趣趣, 它它們的魔魔數(shù)是 T. 查查看其他他類的工工作留給給讀者作作為練習習; eext22_iooctll 是最最有趣的的函數(shù)(并且比比預期的的要容易易理解), 因因為它實實現(xiàn) aappeend-onlly 標標志和 immmutaablee 標志志.下列 iiocttl 命命令是預預定義給給任何文文件, 包括設設

28、備特殊殊的文件件:FIOCCLEXX 設置 cclosse-oon-eexecc 標志志( CClosse oon EEXecc). 設置這這個標志志使文件件描述符符被關閉閉, 當當調用進進程執(zhí)行行一個新新程序時時.FIONNCLEEX 清除 cclosse-nno-eexecc 標志志( NNot CLoose on EXeec). 這個個命令恢恢復普通通文件行行為, 復原上上面 FFIOCCLEXX 所做做的. FIOOASYYNC 為這個個文件設設置或者者復位異異步通知知(如同同在本章章中異異步通知知一節(jié)節(jié)中討論論的). 注意意直到 Linnux 2.22.4 版本的的內核不不正確地地使

29、用這這個命令令來修改改 O_SYNNC 標標志. 因為兩兩個動作作都可通通過 ffcnttl 來來完成, 沒有有人真正正使用 FIOOASYYNC 命令, 它在在這里出出現(xiàn)只是是為了完完整性.FIOQQSIZZE 這個命令令返回一一個文件件或者目目錄的大大小; 當用作作一個設設備文件件, 但但是, 它返回回一個 ENOOTTYY 錯誤誤.FIONNBIOO Noon-BBlocckinng II/O(在阻塞和和非阻塞塞操作一節(jié)中中描述). 這這個調用用修改在在 fiilp-f_flaags 中的 O_NNONBBLOCCK 標標志. 給這個個系統(tǒng)調調用的第第 3 個參數(shù)數(shù)用作指指示是否否這個標

30、標志被置置位或者者清除. (我我們將在在本章看看到這個個標志的的角色). 注注意常用用的改變變這個標標志的方方法是使使用 ffcnttl 系系統(tǒng)調用用, 使使用 FF_SEETFLL 命令令.列表中的的最后一一項介紹紹了一個個新的系系統(tǒng)調用用, ffcnttl, 它看來來象 iiocttl. 事實上上, ffcnttl 調調用非常常類似 iocctl, 它也也是獲得得一個命命令參數(shù)數(shù)和一個個額外的的(可選選地)參參數(shù). 它保持持和 iiocttl 獨獨立主要要是因為為歷史原原因: 當 UUnixx 開發(fā)發(fā)者面對對控制 I/OO 操作作的問題題時, 他們決決定文件件和設備備是不同同的. 那時,

31、有 iocctl 實現(xiàn)的的唯一設設備是 ttyys, 它解釋釋了為什什么 -ENOOTTYY 是標標準的對對不正確確 iooctll 命令令的回答答. 事事情已經(jīng)經(jīng)改變, 但是是 fccntll 保留留為一個個獨立的的系統(tǒng)調調用.6.1.4.使用 iocctl 參數(shù)在看 ssculll 驅驅動的 iocctl 代碼之之前, 我們需需要涉及及的另一一點是如如何使用用這個額額外的參參數(shù). 如果它它是一個個整數(shù), 就容容易: 它可以以直接使使用. 如果它它是一個個指針, 但是是, 必必須小心心些.當用一個個指針引引用用戶戶空間, 我們們必須確確保用戶戶地址是是有效的的. 試試圖存取取一個沒沒驗證過過

32、的用戶戶提供的的指針可可能導致致不正確確的行為為, 一一個內核核 ooops, 系統(tǒng)統(tǒng)崩潰, 或者者安全問問題. 它是驅驅動的責責任來對對每個它它使用的的用戶空空間地址址進行正正確的檢檢查, 并且返返回一個個錯誤如如果它是是無效的的.在第 33 章, 我們們看了 coppy_ffromm_usser 和 ccopyy_too_usser 函數(shù), 它們們可用來來安全地地移動數(shù)數(shù)據(jù)到和和從用戶戶空間. 這些些函數(shù)也也可用在在 iooctll 方法法中, 但是 iocctl 調用常常常包含含小數(shù)據(jù)據(jù)項, 可通過過其他方方法更有有效地操操作. 開始, 地址址校驗(不傳送送數(shù)據(jù))由函數(shù)數(shù) acccess

33、s_ook 實實現(xiàn), 它定義義在 :int acccesss_okk(innt ttypee, cconsst vvoidd *aaddrr, uunsiigneed llongg siize); 第一個參參數(shù)應當當是 VVERIIFY_REAAD 或或者 VVERIIFY_WRIITE, 依據(jù)據(jù)這個要要進行的的動作是是否是讀讀用戶空空間內存存區(qū)或者者寫它. adddr 參數(shù)持持有一個個用戶空空間地址址, ssizee 是一一個字節(jié)節(jié)量. 例如, 如果果 iooctll 需要要從用戶戶空間讀讀一個整整數(shù), sizze 是是 siizeoof(iint). 如如果你需需要讀和和寫給定定地址, 使

34、用用 VEERIFFY_WWRITTE, 因為它它是 VVERIIRY_REAAD 的的超集.不象大部部分的內內核函數(shù)數(shù), aacceess_ok 返回一一個布爾爾值: 1 是是成功(存取沒沒問題)和 00 是失失敗(存存取有問問題). 如果果它返回回假, 驅動應應當返回回 -EEFAUULT 給調用用者.關于 aacceess_ok有有多個有有趣的東東西要注注意. 首先, 它不不做校驗驗內存存存取的完完整工作作; 它它只檢查查看這個個內存引引用是在在這個進進程有合合理權限限的內存存范圍中中. 特特別地, acccesss_ook 確確保這個個地址不不指向內內核空間間內存. 第22, 大大部分

35、驅驅動代碼碼不需要要真正調調用 aacceess_ok. 后面面描述的的內存存存取函數(shù)數(shù)為你負負責這個個. 但但是, 我們來來演示它它的使用用, 以以便你可可見到它它如何完完成.sculll 源源碼利用用了 iiocllt 號號中的位位段來檢檢查參數(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;在調用 acccesss_okk 之后后, 驅驅動可安安全地進進行真正正的傳輸輸. 加加上 ccopyy_frrom_useer 和和 coopy_to_useer_ 函數(shù), 程序序員可利利用一組組為被最最多使用用的數(shù)據(jù)據(jù)大小(1, 2, 4, 和 88 字節(jié)節(jié))而優(yōu)優(yōu)化過的的函數(shù). 這些些函數(shù)在在下面列列表中描描述, 它們定定義在 :put_useer(ddatuum, ptrr) _puut_uuserr(daatumm, pptr) 這些宏定定義寫

39、 dattum 到用戶戶空間; 它們們相對快快, 并并且應當當被調用用來代替替 coopy_to_useer 無無論何時時要傳送送單個值值時. 這些宏宏已被編編寫來允允許傳遞遞任何類類型的指指針到 putt_usser, 只要要它是一一個用戶戶空間地地址. 傳送的的數(shù)據(jù)大大小依賴賴 prrt 參參數(shù)的類類型, 并且在在編譯時時使用 sizzeoff 和 typpeoff 等編編譯器內內建宏確確定. 結果是是, 如如果 pprt 是一個個 chhar 指針, 傳送送一個字字節(jié), 以及對對于 22, 44, 和和 可能能的 88 字節(jié)節(jié).put_useer 檢檢查來確確保這個個進程能能夠寫入入給定

40、的的內存地地址. 它在成成功時返返回 00, 并并且在錯錯誤時返返回 -EFAAULTT. _puut_uuserr 進行行更少的的檢查(它不調調用 aacceess_ok), 但但是仍然然能夠失失敗如果果被指向向的內存存對用戶戶是不可可寫的. 因此此, _puut_uuserr 應當當只用在在內存區(qū)區(qū)已經(jīng)用用 acccesss_ook 檢檢查過的的時候.作為一個個通用的的規(guī)則, 當你你實現(xiàn)一一個 rreadd 方法法時, 調用 _pput_useer 來來節(jié)省幾幾個周期期, 或或者當你你拷貝幾幾個項時時, 因因此, 在第一一次數(shù)據(jù)據(jù)傳送之之前調用用 acccesss_ook 一一次, 如同上

41、上面 iiocttl 所所示.get_useer(llocaal, ptrr) _geet_uuserr(loocall, pptr) 這些宏定定義用來來從用戶戶空間接接收單個個數(shù)據(jù). 它們們象 pput_useer 和和 _putt_usser, 但是是在相反反方向傳傳遞數(shù)據(jù)據(jù). 獲獲取的值值存儲于于本地變變量 llocaal; 返回值值指出這這個操作作是否成成功. 再次, _gett_usser 應當只只用在已已經(jīng)使用用 acccesss_ook 校校驗過的的地址.如果做一一個嘗試試來使用用一個列列出的函函數(shù)來傳傳送一個個不適合合特定大大小的值值, 結結果常常常是一個個來自編編譯器的的奇怪

42、消消息, 例如covverssionn too noon-sscallar typpe rrequuestted. 在在這些情情況中, 必須須使用 coppy_tto_uuserr 或者者 coopy_froom_uuserr.6.1.5.兼容性性和受限限操作存取一個個設備由由設備文文件上的的許可權權控制, 并且且驅動正正常地不不涉及到到許可權權的檢查查. 但但是, 有些情情形, 在保證證給任何何用戶對對設備的的讀寫許許可的地地方, 一些控控制操作作仍然應應當被拒拒絕. 例如, 不是是所有的的磁帶驅驅動器的的用戶都都應當能能夠設置置它的缺缺省塊大大小, 并且一一個已經(jīng)經(jīng)被給予予對一個個磁盤設設

43、備讀寫寫權限的的用戶應應當仍然然可能被被拒絕來來格式化化它. 在這樣樣的情況況下, 驅動必必須進行行額外的的檢查來來確保用用戶能夠夠進行被被請求的的操作.傳統(tǒng)上 uniix 系系統(tǒng)對超超級用戶戶帳戶限限制了特特權操作作. 這這意味著著特權是是一個全全有-或或-全無無的東西西 - 超級級用戶可可能任意意做任何何事情, 但是是所有其其他的用用戶被高高度限制制了. Linnux 內核提提供了一一個更加加靈活的的系統(tǒng), 稱為為能力. 一個個基于能能力的系系統(tǒng)丟棄棄了全有有-或全全無模式式, 并并且打破破特權操操作為獨獨立的子子類. 這種方方式, 一個特特殊的用用戶(或或者是程程序)可可被授權權來進行行

44、一個特特定的特特權操作作而不必必泄漏進進行其他他的, 無關的的操作的的能力. 內核核在許可可權管理理上排他他地使用用能力, 并且且輸出 2 個個系統(tǒng)調調用 ccapgget 和 ccapsset, 來允允許它們們被從用用戶空間間管理.全部能力力可在 中找到到. 這這些是對對系統(tǒng)唯唯一可用用的能力力; 對對于驅動動作者或或者系統(tǒng)統(tǒng)管理員員, 不不可能不不修改內內核源碼碼而來定定義新的的. 設設備驅動動編寫者者可能感感興趣的的這些能能力的一一個子集集, 包包括下面面:CAP_DACC_OVVERRRIDEE 這個能力力來推翻翻在文件件和目錄錄上的存存取的限限制(數(shù)數(shù)據(jù)存取取控制, 或者者 DAAC

45、).CAP_NETT_ADDMINN 進行網(wǎng)絡絡管理任任務的能能力, 包括那那些能夠夠影響網(wǎng)網(wǎng)絡接口口的.CAP_SYSS_MOODULLE 加載或去去除內核核模塊的的能力.CAP_SYSS_RAAWIOO 進行 raww II/O 操作的的能力. 例子子包括存存取設備備端口或或者直接接和 UUSB 設備通通訊.CAP_SYSS_ADDMINN 一個捕獲獲-全部部的能力力, 提提供對許許多系統(tǒng)統(tǒng)管理操操作的存存取.CAP_SYSS_TTTY_CCONFFIG 進行 ttty 配置任任務的能能力.在進行一一個特權權操作之之前, 一個設設備驅動動應當檢檢查調用用進程有有合適的的能力; 不這這樣做可

46、可能導致致用戶進進程進行行非法的的操作, 對系系統(tǒng)的穩(wěn)穩(wěn)定和安安全有壞壞的后果果. 能能力檢查查是通過過 caapabble 函數(shù)來來進行的的(定義義在 ): intt caapabble(intt caapabbiliity); 在 scculll 例子子驅動中中, 任任何用戶戶被許可可來查詢詢 quuanttum 和 qquanntumm 集的的大小. 只有有特權用用戶, 但是, 可改改變這些些值, 因為不不適當?shù)牡闹悼赡苣芎軌牡氐赜绊懴迪到y(tǒng)性能能. 當當需要時時, iiocttl 的的 scculll 實現(xiàn)現(xiàn)檢查用用戶的特特權級別別, 如如下: if (! cappablle (CAPP

47、_SYYS_AADMIIN) retturnn -EEPERRM;在這個任任務缺乏乏一個更更加特定定的能力力時, CAPP_SYYS_AADMIIN 被被選擇來來做這個個測試.6.1.6.iocctl 命令的的實現(xiàn)iocttl 的的 scculll 實現(xiàn)現(xiàn)只傳遞遞設備的的配置參參數(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 個個入口項

52、項作用于于 scculll_qsset. 這些些入口項項和給 scuull_quaantuum 的的是一致致的, 并且不不值得展展示出來來.從調用者者的觀點點看(即即從用戶戶空間), 這這 6 種傳遞遞和接收收參數(shù)的的方法看看來如下下: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 */當然, 一個正正常的驅驅動

54、不可可能實現(xiàn)現(xiàn)這樣一一個調用用模式的的混合體體. 我我們這里里這樣做做只是為為了演示示做事情情的不同同方式. 但是是, 正正常地, 數(shù)據(jù)據(jù)交換將將一致地地進行, 通過過指針或或者通過過值, 并且要要避免混混合這 2 種種技術.6.1.7.不用 iocctl 的設備備控制有時控制制設備最最好是通通過寫控控制序列列到設備備自身來來實現(xiàn). 例如如, 這這個技術術用在控控制臺驅驅動中, 這里里所謂的的 esscappe 序序列被用用來移動動光標, 改變變缺省的的顏色, 或者者進行其其他的配配置任務務. 這這樣實現(xiàn)現(xiàn)設備控控制的好好處是用用戶可僅僅僅通過過寫數(shù)據(jù)據(jù)控制設設備, 不必使使用(或或者有時時候

55、寫)只為配配置設備備而建立立的程序序. 當當設備可可這樣來來控制, 發(fā)出出命令的的程序甚甚至常常常不需要要運行在在和它要要控制的的設備所所在的同同一個系系統(tǒng)上.例如, settterrm 程程序作用用于控制制臺(或或者其他他終端)配置, 通過過打印 esccapee 序列列. 控控制程序序可位于于和被控控制的設設備不同同的一臺臺計算機機上, 因為一一個簡單單的數(shù)據(jù)據(jù)流重定定向可完完成這個個配置工工作. 這是每每次你運運行一個個遠程 ttyy 會話話時所發(fā)發(fā)生的事事情: esccapee 序列列在遠端端被打印印但是影影響到本本地的 ttyy; 然然而, 這個技技術不局局限于 ttyys.通過打印

56、印來控制制的缺點點是它給給設備增增加了策策略限制制; 例例如, 它僅僅僅當你確確信在正正常操作作時控制制序列不不會出現(xiàn)現(xiàn)在正被被寫入設設備的數(shù)數(shù)據(jù)中. 這對對于 tttyss 只是是部分正正確的. 盡管管一個文文本顯示示意味著著只顯示示 ASSCIII 字符符, 有有時控制制字符可可潛入正正被寫入入的數(shù)據(jù)據(jù)中, 并且可可能, 因此, 影響響控制臺臺的配置置. 例例如, 這可能能發(fā)生在在你顯示示一個二二進制文文件到屏屏幕時; 產生生的亂碼碼可能包包含任何何東西, 并且且最后你你常常在在你的控控制臺上上出現(xiàn)錯錯誤的字字體.通過寫來來控制是是當然的的使用方方法了, 對于于不用傳傳送數(shù)據(jù)據(jù)而只是是響應

57、命命令的設設備, 例如遙遙控設備備.例如, 被你們們作者當當中的一一個編寫寫來好玩玩的驅動動, 移移動一個個 2 軸上的的攝像機機. 在在這個驅驅動里, 這個個設備備是一一對老式式步進電電機, 它們不不能真正正讀或寫寫. 給給一個步步進電機機發(fā)送送數(shù)據(jù)流流的概概念沒有有任何意意義. 在這個個情況下下, 驅驅動解釋釋正被寫寫入的數(shù)數(shù)據(jù)作為為 ASSCIII 命令令并且轉轉換這個個請求為為脈沖序序列, 來操縱縱步進電電機. 這個概概念類似似于, 有些, 你發(fā)發(fā)給貓的的 ATT 命令令來建立立通訊, 主要要的不同同是和貓貓通訊的的串口必必須也傳傳送真正正的數(shù)據(jù)據(jù). 直直接設備備控制的的好處是是你可以

58、以使用 catt 來移移動攝像像機, 而不必必寫和編編譯特殊殊的代碼碼來發(fā)出出 iooctll 調用用.當編寫面面向命令令的驅動動, 沒沒有理由由實現(xiàn) iocctl 命令. 一個個解釋器器中的額額外命令令更容易易實現(xiàn)并并使用.有時, 然而, 你可可能選擇擇使用其其他的方方法:不不必轉變變 wrritee 方法法為一個個解釋器器和避免免 iooctll, 你你可能選選擇完全全避免寫寫并且專專門使用用 iooctll 命令令, 而而實現(xiàn)驅驅動為使使用一個個特殊的的命令行行工具來來發(fā)送這這些命令令到驅動動. 這這個方法法轉移復復雜性從從內核空空間到用用戶空間間, 這這里可能能更易處處理, 并且?guī)蛶椭?/p>

59、保持持驅動小小, 而而拒絕使使用簡單單的 ccat 或者 echho 命命令. 但但是, 這個文文件的維維護在后后來有些些少見了了. 實實際上, 所有有的當前前使用的的 liibc 實現(xiàn)(包括 uCllibcc) 僅僅將 -40995 到到 -11 的值值當作錯錯誤碼. 不幸幸的是, 能夠夠返回大大的負數(shù)數(shù)而不是是小的, 沒有有多大用用處.6.2.阻塞 I/OO回顧第 3 章章, 我我們看到到如何實實現(xiàn) rreadd 和 wriite 方法. 在此此, 但但是, 我們跳跳過了一一個重要要的問題題:一個個驅動當當它無法法立刻滿滿足請求求應當如如何響應應? 一一個對 reaad 的的調用可可能當沒

60、沒有數(shù)據(jù)據(jù)時到來來, 而而以后會會期待更更多的數(shù)數(shù)據(jù). 或者一一個進程程可能試試圖寫, 但是是你的設設備沒有有準備好好接受數(shù)數(shù)據(jù), 因為你你的輸出出緩沖滿滿了. 調用進進程往往往不關心心這種問問題; 程序員員只希望望調用 reaad 或或 wrritee 并且且使調用用返回, 在必必要的工工作已完完成后. 這樣樣, 在在這樣的的情形中中, 你你的驅動動應當(缺省地地)阻塞塞進程, 使它它進入睡睡眠直到到請求可可繼續(xù). 本節(jié)展示示如何使使一個進進程睡眠眠并且之之后再次次喚醒它它. 如如常, 但是, 我們們必須首首先解釋釋幾個概概念.6.2.1.睡眠的的介紹對于一個個進程睡眠意味著著什么? 當一一

溫馨提示

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

評論

0/150

提交評論