亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? (ldd) ch02-編寫和運(yùn)行模塊(轉(zhuǎn)載).htm

?? Linux設(shè)備驅(qū)動(dòng)程序用于開發(fā)LINUX
?? HTM
?? 第 1 頁 / 共 4 頁
字號(hào):
      color=#ffffff size=3>
      <P><BR>正如函數(shù)register_symtab的名字所暗示,它用來在內(nèi)核主符號(hào)表中注冊(cè)符號(hào)表。這種方<BR>法要比通過靜態(tài)和全局變量的方法清晰的多,這樣程序員就可以把關(guān)于哪些開放給其他<BR>模塊,哪些不開放的信息集中存放。這種方法比在源文件中到處堆放static聲明要好的<BR>多。<BR>&nbsp;<BR>如果模塊在初始化過程中調(diào)用了register_symtab,全局變量就不再是開放的了;只有那<BR>些顯式羅列在符號(hào)表中的符號(hào)才開放給內(nèi)核。<BR>&nbsp;<BR>填寫一個(gè)符號(hào)表是項(xiàng)挺復(fù)雜的工作,但內(nèi)核開發(fā)人員已經(jīng)寫好了頭文件簡(jiǎn)化這項(xiàng)工作。<BR>下面若干行代碼演示了如何聲明和開放一個(gè)符號(hào)表:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>有興趣的讀者可以看看&lt;linux/symtab_begin.h&gt;,但它可是內(nèi)核中最難懂的頭文件之一<BR>。事實(shí)上,僅想好好使用宏X的話,根本沒必要讀董它。<BR>&nbsp;<BR>由于register_symtab是在模塊加載到內(nèi)核后被調(diào)用的,它可以覆蓋模塊靜態(tài)或全局聲明<BR>的符號(hào)。此時(shí),register_symtab用顯式符號(hào)表替代模塊默認(rèn)開放的公共符號(hào)。<BR>&nbsp;<BR>這種覆蓋是可能的,因?yàn)閕nsmod命令處理傳遞給系統(tǒng)調(diào)用sys_init_module的全局符號(hào)表<BR>,然后在調(diào)用init_module之前注冊(cè)這個(gè)符號(hào)表。因此這之后的任何一次顯式調(diào)用regist<BR>er_symtab都會(huì)替換相應(yīng)模塊的符號(hào)表。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>er_symtab都會(huì)替換相應(yīng)模塊的符號(hào)表。<BR>&nbsp;<BR>如果你的模塊不需要開放任何符號(hào),而且你也不想把所有的東西都聲明成static的,在i<BR>nit_module里加上下面一行語句就可以了。這次對(duì)register_symtab的調(diào)用通過注冊(cè)一個(gè)<BR>空表覆蓋了模塊默認(rèn)的符號(hào)表:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>如果源文件不想給堆疊在其上的模塊提供什么接口,用上面那行語句隱藏所有的符號(hào)總<BR>是不錯(cuò)的。<BR>&nbsp;<BR>當(dāng)模塊從內(nèi)&nbsp;誦對(duì)厥&nbsp;,它所聲明的所有公共符號(hào)也就自動(dòng)?主符號(hào)表中注銷了。不過是<BR>全局符號(hào)還是顯式符號(hào)表,這一點(diǎn)都適用。<BR>&nbsp;<BR>初始化和終止<BR>正如前面已述,init_module向內(nèi)核注冊(cè)模塊所能提供的所有設(shè)施。這里我使用了“設(shè)施<BR>”,我的意思是指新功能,是一整個(gè)設(shè)備驅(qū)動(dòng)程序或新軟件抽象,是一個(gè)可以由應(yīng)用程<BR>序使用的新功能。<BR>&nbsp;<BR>通過調(diào)用內(nèi)核函數(shù)完成新設(shè)施的注冊(cè)。傳遞的參數(shù)通常為一個(gè)指向描述這個(gè)新設(shè)施的數(shù)<BR>據(jù)結(jié)構(gòu)和要注冊(cè)的設(shè)施名稱。這個(gè)數(shù)據(jù)結(jié)構(gòu)通常會(huì)包含一些指向模塊函數(shù)的指針,這就<BR>是模塊體內(nèi)的函數(shù)是被調(diào)用的機(jī)制。<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>除了用來標(biāo)別模塊類別(如字符和塊設(shè)備驅(qū)動(dòng)程序)的“主”設(shè)施之外,模塊還可以注<BR>冊(cè)如下項(xiàng)目:<BR>&nbsp;<BR>其他設(shè)備<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;由于這類設(shè)施僅僅用于總線型鼠標(biāo),這些設(shè)備曾一度稱為鼠標(biāo)設(shè)備。它們都是些<BR>不完整的設(shè)備,通常要比那些功能健全的設(shè)備簡(jiǎn)單。<BR>&nbsp;<BR>串行端口<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;可以在運(yùn)行時(shí)向系統(tǒng)里加入串口設(shè)備驅(qū)動(dòng)程序;這也是支持PCMCIA調(diào)治解調(diào)器的<BR>機(jī)制。<BR>&nbsp;<BR>行律<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;行律是處理終端數(shù)據(jù)流的軟件層。模塊可以注冊(cè)新行律,以非標(biāo)準(zhǔn)方式處理終端<BR>事務(wù)。例如,模塊kmouse就使用行律從串口鼠標(biāo)中偷取數(shù)據(jù)。<BR>&nbsp;<BR>終端設(shè)備驅(qū)動(dòng)程序<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;終端設(shè)備驅(qū)動(dòng)程序一組實(shí)現(xiàn)終端底層數(shù)據(jù)處理的函數(shù)。控制臺(tái)和串口設(shè)備驅(qū)動(dòng)程<BR>序?yàn)榱藙?chuàng)建終端設(shè)備,它們都要注冊(cè)自己的驅(qū)動(dòng)程序。而多端口串口則有自己的驅(qū)動(dòng)程<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>序?yàn)榱藙?chuàng)建終端設(shè)備,它們都要注冊(cè)自己的驅(qū)動(dòng)程序。而多端口串口則有自己的驅(qū)動(dòng)程<BR>序。<BR>&nbsp;<BR>/proc文件<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/proc包含了用來訪問內(nèi)核信息的文件。由于它們也可以用來調(diào)試,第4章的“使<BR>用/proc文件系統(tǒng)”將講解/proc文件。<BR>&nbsp;<BR>二進(jìn)制文件格式<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;對(duì)于每個(gè)可執(zhí)行文件,內(nèi)核掃描“二進(jìn)制文件格式”列表并按相應(yīng)的格式執(zhí)行它<BR>。模塊可以實(shí)現(xiàn)新的格式,Java模塊就是這樣做的。<BR>&nbsp;<BR>Exec域<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;為了提供與其他流行Unix系統(tǒng)的兼容,必須修改內(nèi)核的某些內(nèi)部表格。一個(gè)“執(zhí)<BR>行域”就是一組從其他操作系統(tǒng)約定到Linux系統(tǒng)的映射。例如,模塊可以定義執(zhí)行SCO<BR>二進(jìn)制文件的執(zhí)行域。<BR>&nbsp;<BR>符號(hào)表<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;這個(gè)已在前面的“注冊(cè)符號(hào)表”小節(jié)中介紹了。<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>上面這些項(xiàng)目都不是前一章所考慮的設(shè)備類型,而且都支持那些通常集成到驅(qū)動(dòng)程序功<BR>能中的設(shè)施,如/proc文件和行律。之所以鼠標(biāo)和其他設(shè)備驅(qū)動(dòng)程序都沒有象“完整”字<BR>符設(shè)備那樣管理,這主要是為了方便。過一會(huì)兒,當(dāng)你讀到第3章“字符設(shè)備”的“主從<BR>設(shè)備號(hào)”小節(jié)時(shí),原因就明了了。<BR>&nbsp;<BR>還可以將模塊注冊(cè)為某些驅(qū)動(dòng)程序的附件,但這樣做就太特殊了,這里就不作討論了;<BR>它們都使用了“注冊(cè)符號(hào)表”中講到的堆疊技術(shù)。如果你想做更深一步的探究,你可以<BR>在內(nèi)核源碼中查查register_symtab,并且找找不同驅(qū)動(dòng)程序的入口點(diǎn)。大部分注冊(cè)函數(shù)<BR>都是以register_開始的,這樣你就可以用“register_”在/proc/ksyms找找它們了。<BR>&nbsp;<BR>init_module中的錯(cuò)誤處理<BR>如果你注冊(cè)時(shí)發(fā)生什么錯(cuò)誤,你必須取消失敗前所有已完成的注冊(cè)。例如,如果系統(tǒng)沒<BR>有足夠內(nèi)存分配新數(shù)據(jù)結(jié)構(gòu)時(shí),可能會(huì)發(fā)生錯(cuò)誤。盡管這不太可能,但確實(shí)會(huì)發(fā)生,好<BR>的程序代碼必須為處理這類事件做好準(zhǔn)備。<BR>&nbsp;<BR>Linux不為每個(gè)模塊保留它都注冊(cè)了那些設(shè)施,因此當(dāng)init_module在某處失敗時(shí),模塊<BR>必須統(tǒng)統(tǒng)收回。如果你在注銷你已經(jīng)注冊(cè)的設(shè)施時(shí)失敗了,內(nèi)核就進(jìn)入一種不穩(wěn)定狀態(tài)<BR>:卸載模塊后,由于它們看起來仍然是“忙”的,你再也不能注冊(cè)那些設(shè)施了,而且你<BR>也無法注銷它們了,因?yàn)槟惚仨毷褂媚阕?cè)時(shí)的那個(gè)指針,而你不太可能得到那個(gè)指針<BR>了。恢復(fù)這種情況非常復(fù)雜,通常,重新啟動(dòng)是最好的解決方法。<BR>&nbsp;<BR>我建議你用goto語句處理錯(cuò)誤恢復(fù)。我討厭使用goto,但以我個(gè)人來看,這是一個(gè)它有<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>我建議你用goto語句處理錯(cuò)誤恢復(fù)。我討厭使用goto,但以我個(gè)人來看,這是一個(gè)它有<BR>所做為的地方(而且,是唯一的地方)。在內(nèi)核里,通常都會(huì)象這里處理錯(cuò)誤那樣使用g<BR>oto。<BR>&nbsp;<BR>下面這段樣例在成功和失敗時(shí)都能正確執(zhí)行:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>返回值(err)是一個(gè)錯(cuò)誤編碼。在Linux內(nèi)核里,錯(cuò)誤編碼是一個(gè)負(fù)值,在&lt;linux/errn<BR>o.h&gt;中定義。如果你不使用其他函數(shù)返回的錯(cuò)誤編碼而要生成自己的,你應(yīng)該包含&lt;linu<BR>x/errno.h&gt;,這樣就可以使用諸如-ENODEV,-ENOMEM之類的符號(hào)值。總是返回相應(yīng)的錯(cuò)<BR>誤編碼是種非常好的習(xí)慣,因?yàn)檫@樣一來用戶程序就利用perror或相似的方法把它們轉(zhuǎn)<BR>換成有意義的字符串了。<BR>&nbsp;<BR>很明顯,cleanup_module要取消所有init_module中完成的注冊(cè)。<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>使用計(jì)數(shù)<BR>為了確定模塊是否可以安全地卸載,系統(tǒng)為每個(gè)模塊保留了一個(gè)使用計(jì)數(shù)。由于模塊忙<BR>的時(shí)候是不能卸載模塊的,系統(tǒng)需要這些信息:當(dāng)文件系統(tǒng)還被安裝在系統(tǒng)上時(shí)就不能<BR>刪除這個(gè)文件系統(tǒng)類型,而且你也不能在還有程序使用某個(gè)字符設(shè)備時(shí)就去掉它。<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>如果忘了更新使用計(jì)數(shù),你就不能再卸載模塊了。在開發(fā)期間這種情況很可能發(fā)生,所<BR>以你一定要牢記。例如,如果進(jìn)程因你的驅(qū)動(dòng)程序引用了NULL指針而終止,驅(qū)動(dòng)程序就<BR>不可能區(qū)關(guān)閉設(shè)備,使用計(jì)數(shù)也就無法回復(fù)到0。一種可能的解決方法就是在調(diào)試期間完<BR>全不使用使用計(jì)數(shù),將MOD_INC_USE_COUNT和MOD_DEC_USE_COUNT重新定義為空操作。另<BR>一個(gè)解決方法就是利用其他方法將計(jì)數(shù)強(qiáng)制復(fù)位為0(在第5章的“使用ioctl參數(shù)”小節(jié)<BR>中介紹)。在編寫成品模塊時(shí),決不能投機(jī)取巧。然而在調(diào)試時(shí)期,有時(shí)候忽略一些問<BR>題可以節(jié)省時(shí)間,是可以接受的。<BR>&nbsp;<BR>使用計(jì)數(shù)的當(dāng)前值可以在/proc/modules中每一項(xiàng)的第3個(gè)域中找到。這個(gè)文件顯式系統(tǒng)<BR>中當(dāng)前共加載了那些模塊,每一項(xiàng)對(duì)應(yīng)一個(gè)模塊。其中的域包括,模塊名,模塊使用的<BR>頁面數(shù)和當(dāng)前使用計(jì)數(shù)。這是一個(gè)/proc/modules樣例:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>(autoclean)標(biāo)志表明模塊由kerneld管理(見第11章)。較新的內(nèi)核中又加入了一些新<BR>的標(biāo)志,除了一件事外,/proc/modules的基本結(jié)構(gòu)完全相同:在內(nèi)核2.1.18和更新的版<BR>本中,長(zhǎng)度用字節(jié)計(jì)而不是頁面計(jì)。<BR>&nbsp;<BR>卸載<BR>要卸載一個(gè)模塊就要使用rmmod命令。由于無需連編,它的任務(wù)遠(yuǎn)比加載簡(jiǎn)單。這個(gè)命令<BR>調(diào)用系統(tǒng)調(diào)用delete_module,如果使用計(jì)數(shù)為0它又調(diào)用模塊的cleanup_module。<BR>&nbsp;<BR>cleanup_module實(shí)現(xiàn)負(fù)責(zé)注銷所有由模塊已經(jīng)注冊(cè)了的項(xiàng)目。只有符號(hào)表是自動(dòng)刪除的<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>cleanup_module實(shí)現(xiàn)負(fù)責(zé)注銷所有由模塊已經(jīng)注冊(cè)了的項(xiàng)目。只有符號(hào)表是自動(dòng)刪除的<BR>。<BR>&nbsp;<BR>使用資源<BR>模塊不使用資源是無法完成自己的任務(wù)的,這些資源包括內(nèi)存,I/O端口和中斷,如果你<BR>要用DMA控制器的話,還得有DMA通道。<BR>&nbsp;<BR>做為一個(gè)程序員,你一定已經(jīng)習(xí)慣了內(nèi)存分配管理,在這方面編寫內(nèi)核代碼沒什么區(qū)別<BR>。你的程序使用kmalloc分配內(nèi)存,使用kfree釋放內(nèi)存。除了kmalloc多一個(gè)參數(shù),優(yōu)先<BR>級(jí),外,它們和malloc,free很相似。很多情況下,用優(yōu)先級(jí)GFP_KERNEL就可以了。縮<BR>寫GFP代表“Get&nbsp;Free&nbsp;Page(獲取空閑頁面)。”<BR>&nbsp;<BR>與此不同,獲取I/O端口和中斷乍聽起來怪怪的,因?yàn)槌绦騿T一般同用顯式的指令訪問它<BR>們,不必讓操作系統(tǒng)了解這些。“分配”端口和中斷與分配內(nèi)存不同,因?yàn)閮?nèi)存是從一<BR>個(gè)資源池中分配,并且每個(gè)地址的行為是一樣的;I/O端口都各有自己的作用,而且驅(qū)動(dòng)<BR>程序需要在特定的端口上工作,而不能隨便使用某個(gè)端口。<BR>&nbsp;<BR>端口<BR>對(duì)于大多數(shù)驅(qū)動(dòng)程序而言,它們的典型工作就是讀寫端口。不管是初始化還是正常工作<BR>的時(shí)候,它們都是這樣的。為了避免其他驅(qū)動(dòng)程序的干擾,必須保證設(shè)備驅(qū)動(dòng)程序以獨(dú)<BR>占方式訪問端口――如果一個(gè)模塊探測(cè)因自己的硬件而寫某個(gè)端口,而恰巧這個(gè)端口又<BR>是屬于另一個(gè)設(shè)備的,這之后一定會(huì)發(fā)生點(diǎn)怪事。<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>為了防止不同設(shè)備間的干擾,Linux的開發(fā)者決定實(shí)現(xiàn)端口的請(qǐng)求/釋放機(jī)制。然而,未<BR>授權(quán)的對(duì)端口的訪問并不會(huì)產(chǎn)生類似于“段失效”那樣的錯(cuò)誤――硬件無法支持端口注<BR>冊(cè)。<BR>&nbsp;<BR>從文件/proc/ioports可以以文本方式獲得已注冊(cè)的端口信息,就象下面的樣子:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>文件中的每一項(xiàng)是有驅(qū)動(dòng)程序鎖定的范圍(以十六進(jìn)制表示)。在這些被釋放前,其他<BR>驅(qū)動(dòng)程序不允許訪問這些端口。<BR>&nbsp;<BR>避免沖突有兩個(gè)途徑。首先,向系統(tǒng)增加新設(shè)備的用戶檢查/proc/ioports,然后在配置<BR>新設(shè)備使用空閑端口――這種方法假設(shè)設(shè)備可以通過跳線進(jìn)行配置。然后,當(dāng)軟件驅(qū)動(dòng)<BR>程序初始化自己時(shí),它能自動(dòng)探測(cè)新設(shè)備而對(duì)其他設(shè)備無害:驅(qū)動(dòng)程序不會(huì)探測(cè)已由其<BR>他驅(qū)動(dòng)程序使用的I/O端口。<BR>&nbsp;<BR>事實(shí)上,基于I/O注冊(cè)的沖突避免對(duì)于模塊化驅(qū)動(dòng)程序很合適,但對(duì)于連編到內(nèi)核里的驅(qū)<BR>動(dòng)程序來說卻可能失敗。盡管我們不涉及這種驅(qū)動(dòng)程序,但還是很是必要注意到,對(duì)于<BR>一個(gè)在啟動(dòng)時(shí)初始化自己的驅(qū)動(dòng)程序來說,由于它要使用之后會(huì)被注冊(cè)的端口,很可能<BR>會(huì)造成對(duì)其他設(shè)備的誤配置。雖然如此,還是沒有辦法讓一個(gè)符合規(guī)范的驅(qū)動(dòng)程序與已<BR>配置好的硬件交互,除非以前加載的驅(qū)動(dòng)程序不注冊(cè)它的端口。基于以上原因,探測(cè)ISA<BR>設(shè)備是件很危險(xiǎn)的事,而且如果隨正式Linux內(nèi)核發(fā)行的驅(qū)動(dòng)程序?yàn)榱艘蚺c尚未加載的模<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>設(shè)備是件很危險(xiǎn)的事,而且如果隨正式Linux內(nèi)核發(fā)行的驅(qū)動(dòng)程序?yàn)榱艘蚺c尚未加載的模<BR>塊對(duì)應(yīng)的設(shè)備交互,拒絕在模塊加載時(shí)執(zhí)行探測(cè)功能。<BR>&nbsp;<BR>設(shè)備探測(cè)的問題是因?yàn)橹挥幸环N方法標(biāo)別設(shè)備,即通過寫目標(biāo)端口然后再讀的方法――<BR>處理器(而且是任何程序)只能查看數(shù)據(jù)線上的電子信號(hào)。驅(qū)動(dòng)程序編寫者知道一旦設(shè)<BR>備連接到某個(gè)特定的端口上,它就會(huì)響應(yīng)相應(yīng)的查詢代碼。但是如果另一個(gè)設(shè)備連到了<BR>端口上,程序仍然會(huì)寫這個(gè)設(shè)備,但天知道它會(huì)怎么響應(yīng)這個(gè)異常的探測(cè)操作。有時(shí)可<BR>以通過讀外設(shè)的BIOS,查看一個(gè)已知的字串來避免端口探測(cè);已有若干SCSI設(shè)備使用了<BR>這種技術(shù),但并不是每個(gè)設(shè)備都要有自己的BIOS。<BR>&nbsp;<BR>一個(gè)符合規(guī)范的驅(qū)動(dòng)程序應(yīng)該調(diào)用check_region查看是否某個(gè)端口區(qū)域已由其他驅(qū)動(dòng)程<BR>序鎖定,之后就用request_region將端口鎖住,當(dāng)驅(qū)動(dòng)程序不再使用端口時(shí)調(diào)用release<BR>_region釋放端口。這些函數(shù)的原型在&lt;linux/ioports.h&gt;中。<BR>&nbsp;<BR>注冊(cè)端口的典型順序如下所示(函數(shù)skull_probe_hw包含了所有設(shè)備相關(guān)代碼,這里沒<BR>有出現(xiàn)):<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>在cleanup_module里釋放端口:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P><BR>系統(tǒng)也使用了一套類似的請(qǐng)求/釋放策略維護(hù)中斷,但注冊(cè)/注銷中斷比處理端口復(fù)雜,<BR>整個(gè)過程的詳細(xì)解釋將放在第9章“中斷處理”中介紹。<BR>&nbsp;<BR>與前面講到的關(guān)于設(shè)施的注冊(cè)/注銷相似,對(duì)資源的請(qǐng)求/釋放方法也適合使用已勾勒的<BR>基于goto的實(shí)現(xiàn)框架。<BR>&nbsp;<BR>對(duì)于編寫PCI設(shè)備驅(qū)動(dòng)程序的人來說,不存在這里所講的探測(cè)問題。我將在第15章“外部<BR>總線簡(jiǎn)介”中介紹。<BR>&nbsp;<BR>ISA內(nèi)存<BR>本節(jié)技術(shù)性很強(qiáng),如果你對(duì)處理硬件問題不是很有把握,可以簡(jiǎn)單跳過這節(jié)。<BR>&nbsp;<BR>在Intel平臺(tái)上,ISA槽上的目標(biāo)設(shè)備可能會(huì)提供片上內(nèi)存,范圍在640KB到1MB之間(0xA<BR>0000到0xFFFFF);這也是設(shè)備驅(qū)動(dòng)程序可以使用的一類資源。<BR>&nbsp;<BR>這種內(nèi)存部件反映了8086處理器那個(gè)時(shí)代,當(dāng)時(shí)8086的尋址只有一兆的大小。PC設(shè)計(jì)人<BR>員決定,低端的640KB當(dāng)做RAM,而保留另外的384KB用于ROM和內(nèi)存映射設(shè)備。今天,即<BR>便是最強(qiáng)力的個(gè)人電腦也還有這個(gè)在第一兆字節(jié)里的空洞。Linux的PC版保留了這片內(nèi)存<BR>,根本不考慮使用它。本節(jié)給出的代碼可以讓你訪問這個(gè)區(qū)域的內(nèi)存,但它僅限于x86平<BR>臺(tái),而且Linux內(nèi)核要至少是2.0.x的,x是多少都可以。2.1版改變了物理內(nèi)存的訪問方<BR>式,比如,640KB-1MB這段范圍內(nèi)的I/O內(nèi)存就不能再這樣訪問。訪問I/O內(nèi)存的正確方式<BR>是第18章“硬件管理”“低1M內(nèi)的ISA內(nèi)存”小節(jié)中的內(nèi)容,這超出了本章的范圍。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>是第18章“硬件管理”“低1M內(nèi)的ISA內(nèi)存”小節(jié)中的內(nèi)容,這超出了本章的范圍。<BR>&nbsp;<BR>盡管內(nèi)核提供了端口和中斷的請(qǐng)求/釋放機(jī)制,當(dāng)前它還是沒能提供給I/O內(nèi)存類似的機(jī)<BR>制,所以你得自己做了。如果我能理解Linus是如何看待PC體系結(jié)構(gòu)的化,這里給的方法<BR>就不會(huì)變化了。<BR>&nbsp;<BR>有時(shí)某個(gè)驅(qū)動(dòng)程序需要在初始化時(shí)探測(cè)ISA內(nèi)存;例如,我需要告訴視頻截取器(frame<BR>grabber)在哪映射截取的圖象。問題是,如果沒有探測(cè)方法,我將無法辨別那段范圍內(nèi)<BR>哪塊內(nèi)存正在使用。人們需要能夠辨別3種不同的情況:映射了RAM,有ROM(例如,VGA<BR>BIOS),或者那段區(qū)域空閑。<BR>&nbsp;<BR>skull樣例給出一種處理這些內(nèi)存的方法,但由于skull和物理設(shè)備無關(guān),它打印完640KB<BR>-1MB這段內(nèi)存區(qū)域的信息后就退出了。然而,有必要談一談?dòng)糜诜治鰞?nèi)存的代碼,因?yàn)?lt;BR>它必須處理一些競(jìng)爭(zhēng)條件。競(jìng)爭(zhēng)條件就是這樣一種情形,兩個(gè)任務(wù)可以競(jìng)爭(zhēng)同一個(gè)資源<BR>,而且未同步的操作可能會(huì)損壞系統(tǒng)。<BR>&nbsp;<BR>盡管驅(qū)動(dòng)程序編寫者無需處理多任務(wù),我們還是必須記住,中斷可能在你的代碼中間發(fā)<BR>生,而且中斷處理函數(shù)可能會(huì)不提醒你就修改全局量。盡管內(nèi)核提供了許多工具處理競(jìng)<BR>爭(zhēng)條件,下面給得出的簡(jiǎn)單規(guī)則闡述了處理這個(gè)問題的方法;對(duì)這個(gè)問題的徹底對(duì)策將<BR>在第9章的“競(jìng)爭(zhēng)條件”小節(jié)中給出。<BR>&nbsp;<BR>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果僅僅是讀取共享的量,而不是寫,將其聲明為volatile,要求編譯器不對(duì)<BR>其進(jìn)行優(yōu)化。這樣,編譯好的代碼在每次源碼讀取它時(shí)讀取這個(gè)量了。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>其進(jìn)行優(yōu)化。這樣,編譯好的代碼在每次源碼讀取它時(shí)讀取這個(gè)量了。<BR>&nbsp;<BR>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;如果代碼需要檢查和修改這個(gè)值,必須在操作期間關(guān)閉中斷,這樣可以防止其<BR>他進(jìn)程在我們檢查過這個(gè)值后,但恰恰又在我們修改這個(gè)量之前修改這個(gè)量。<BR>&nbsp;<BR>我們建議采用如下關(guān)閉中斷的順序:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>這里cli代表“clear&nbsp;interrupt&nbsp;flag(清除中斷標(biāo)志)”。上面出現(xiàn)的函數(shù)都定義在&lt;a<BR>sm/system.h&gt;中。<BR>&nbsp;<BR>應(yīng)該避免使用經(jīng)典的cli和sti序列,因?yàn)橛袝r(shí)你無法在關(guān)閉中斷前斷定中斷是否打開了<BR>。如果此時(shí)調(diào)用sti就是產(chǎn)生很不規(guī)則的錯(cuò)誤出現(xiàn),很難追蹤這樣的錯(cuò)誤。<BR>&nbsp;<BR>由于那段內(nèi)存只能通過寫物理內(nèi)存和讀取檢查才能標(biāo)別,而且如果測(cè)試期間有中斷的化<BR>,有可能會(huì)被其他程序修改,因此檢查RAM段的代碼同時(shí)利用了volatile聲明和cli。下<BR>面的這段代碼并不是很簡(jiǎn)單,如果一個(gè)設(shè)備正在象它的內(nèi)存寫數(shù)據(jù),而這段代碼又在掃<BR>描這段區(qū)域,它就會(huì)誤認(rèn)為這段區(qū)域是空閑區(qū)。好在這樣的情況很少發(fā)生。<BR>&nbsp;<BR>在下面的源代碼中,每個(gè)printk都帶有一個(gè)KERN_INFO前綴。這個(gè)符號(hào)拼接在格式字串前<BR>面做消息的優(yōu)先級(jí),它定義在&lt;linux/kernel.h&gt;中。這個(gè)符號(hào)展開后與本章開始的hello<BR>..c中使用的&lt;1&gt;字串很相似。<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>..c中使用的&lt;1&gt;字串很相似。<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>如果你在探測(cè)時(shí)注意恢復(fù)你所修改的字節(jié),探測(cè)內(nèi)存不會(huì)造成與其他設(shè)備的沖突。*<BR>&nbsp;<BR>作為一個(gè)細(xì)心的讀者,你可能會(huì)知道在15MB-16MB地址域內(nèi)的ISA內(nèi)存是怎么回事。很不<BR>幸,那是個(gè)更棘手的問題,我們將在第8章的“1M以上的ISA內(nèi)存”小節(jié)中討論。<BR>&nbsp;<BR>自動(dòng)和手動(dòng)配置<BR>根據(jù)系統(tǒng)的不同,驅(qū)動(dòng)程序需要了解的若干參數(shù)也會(huì)隨之變化。例如,設(shè)備必須了解硬<BR>件的I/O地址或內(nèi)存區(qū)域。<BR>&nbsp;<BR>注意,本節(jié)所討論的大部分問題并不適用于PCI設(shè)備(第15章介紹)。<BR>&nbsp;<BR>根據(jù)設(shè)備的不同,除了I/O地址外,還有一些其他參數(shù)會(huì)影響系統(tǒng)的驅(qū)動(dòng)程序的行為,如<BR>設(shè)備的品牌和發(fā)行號(hào)。驅(qū)動(dòng)程序?yàn)榱苏_地工作有必要了解這些參數(shù)的具體值。用正確<BR>的數(shù)值設(shè)置驅(qū)動(dòng)程序(即,配置它)是一項(xiàng)需要在初始化期間完成的復(fù)雜的任務(wù)。<BR>&nbsp;<BR>基本說來,有兩種方式可以獲得這些正確的數(shù)值:或者是用戶顯式地給出它們,或者是<BR>驅(qū)動(dòng)程序自己探測(cè)。無疑,自動(dòng)探測(cè)是最好的驅(qū)動(dòng)程序配置方法,而用戶配置則是最好<BR>實(shí)現(xiàn)的;作為驅(qū)動(dòng)程序編寫者的一種權(quán)衡,他應(yīng)該盡可能地實(shí)現(xiàn)自動(dòng)配置,但又允許用<BR>戶配置作為一種可選的方式替代自動(dòng)配置。這種配置方法的另一個(gè)好處就是,在開發(fā)期<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>戶配置作為一種可選的方式替代自動(dòng)配置。這種配置方法的另一個(gè)好處就是,在開發(fā)期<BR>間可以給定參數(shù),從而不用自動(dòng)探測(cè),可以在以后實(shí)現(xiàn)它。<BR>&nbsp;<BR>insmod在加載時(shí)接受命令行中給定的整數(shù)和字串值,可以給參數(shù)賦值。這條命令可以修<BR>改在模塊中定義的全局變量。例如,如果你的源碼中包含了這些變量:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>那么你就可以使用如下命令加載模塊:<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>例子里使用了printk,它可以顯式,當(dāng)init_module被調(diào)用時(shí),賦值已經(jīng)發(fā)生了。注意,<BR>insmod可以給任何整型或字符指針變量賦值,不管它們是否是公共符號(hào)表中的一部分。<BR>但對(duì)于聲明為數(shù)組的串是不能在加載時(shí)賦值的,因?yàn)樗呀?jīng)在編譯時(shí)解析出來了,以后<BR>就不能修改了。<BR>&nbsp;<BR>自動(dòng)配置可以設(shè)計(jì)為按如下方式工作:“如果配置變量是默認(rèn)值,就執(zhí)行自動(dòng)探測(cè);否<BR>則,保留當(dāng)前值。”為了讓這種方法可以工作,“默認(rèn)”值應(yīng)該不是任何用戶可以在加<BR>載時(shí)設(shè)定的值。<BR>&nbsp;<BR>下面這段代碼給出了skull是如何自動(dòng)探測(cè)設(shè)備的端口地址的。在這個(gè)例子中,使用自動(dòng)<BR>探測(cè)查找多個(gè)設(shè)備,而手動(dòng)配置只限于一個(gè)設(shè)備。注意,函數(shù)skull_detect在上面已經(jīng)<BR></P></FONT><FONT 
      color=#ffffff size=3>
      <P>探測(cè)查找多個(gè)設(shè)備,而手動(dòng)配置只限于一個(gè)設(shè)備。注意,函數(shù)skull_detect在上面已經(jīng)<BR>給出了,而skull_init_board負(fù)責(zé)完成設(shè)備相關(guān)的初始化工作,這里沒有給出。<BR>&nbsp;<BR>(代碼)<BR>&nbsp;<BR>為了方便用戶在insmod命令行中給出相應(yīng)的參數(shù),而且如果這些符號(hào)不會(huì)放到主符號(hào)表<BR>中的話,實(shí)際使用的驅(qū)動(dòng)程序可以去掉配置變量的前綴(在本例中就是skull_)。如果<BR>它們確實(shí)要放到主符號(hào)表中,好的辦法就是聲明兩個(gè)符號(hào):一個(gè)沒有前綴,在加載時(shí)賦<BR>值,一個(gè)有前綴,用register_symtab放到符號(hào)表中。<BR>&nbsp;<BR>在用戶空間編寫驅(qū)動(dòng)程序<BR>到現(xiàn)在為止,一個(gè)首次接觸內(nèi)核問題的Unix程序員困難會(huì)對(duì)編寫模塊非常緊<BR>--<BR>&nbsp;<BR><FONT 
      color=#00ff00>※&nbsp;來源:.華南網(wǎng)木棉站&nbsp;bbs.gznet.edu.cn.[FROM:&nbsp;202.38.196.234]</FONT><BR>--<BR><FONT 
      color=#00ffff>※&nbsp;轉(zhuǎn)寄:.華南網(wǎng)木棉站&nbsp;bbs.gznet.edu.cn.[FROM:&nbsp;211.80.41.106]</FONT><BR>--<BR><FONT 
      color=#0000ff>※&nbsp;轉(zhuǎn)寄:.華南網(wǎng)木棉站&nbsp;bbs.gznet.edu.cn.[FROM:&nbsp;211.80.41.106]</FONT><BR>--<BR><FONT 
      color=#ffff00>※&nbsp;轉(zhuǎn)載:.南京大學(xué)小百合站&nbsp;bbs.nju.edu.cn.[FROM:&nbsp;211.80.41.106]</FONT><BR>&nbsp;<BR>--<BR><FONT 
      color=#ff0000>※&nbsp;轉(zhuǎn)載:·飲水思源&nbsp;bbs.sjtu.edu.cn·[FROM:&nbsp;211.80.41.106]</FONT><BR></P></FONT>
      <P align=center><A 
      href="http://211.71.69.201/joyfire/lsdp/index.htm"><FONT color=#ffffff 
      size=2>目錄頁</FONT></A> | <A 
      href="http://211.71.69.201/joyfire/lsdp/3.htm"><FONT color=#ffffff 
      size=2>上一頁</FONT></A> | <A 
      href="http://211.71.69.201/joyfire/lsdp/5.htm"><FONT color=#ffffff 
      size=2>下一頁</FONT></A></P></SPAN></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width="90%" align=center border=0>
  <TBODY>
  <TR>
    <TD colSpan=3 height=2>
      <TABLE cellSpacing=0 cellPadding=0 width="100%" bgColor=#666666 
        border=0><TBODY>

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號(hào) Ctrl + =
減小字號(hào) Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
亚洲伦理在线免费看| 久久久久久久久蜜桃| 亚洲一区电影777| 欧美三级电影网站| 日韩电影免费一区| 欧美精品一区二区三区蜜桃| 激情综合色播激情啊| 国产亚洲精品精华液| 成人精品视频.| 一区二区三区在线不卡| 欧美二区三区91| 国产一区二区视频在线| 日韩理论在线观看| 欧美精品乱码久久久久久按摩| 蜜臀99久久精品久久久久久软件| 精品91自产拍在线观看一区| 国产成人av福利| 一区二区成人在线| 欧美电影免费观看高清完整版| 国产成人在线网站| 有码一区二区三区| 欧美大尺度电影在线| 粗大黑人巨茎大战欧美成人| 亚洲自拍偷拍九九九| 久久人人超碰精品| 在线观看日韩毛片| 国产精品一二三四五| 亚洲一区免费在线观看| 久久美女高清视频| 在线看国产一区二区| 国产一区二区三区不卡在线观看| 国产精品高潮久久久久无| 91精品国产丝袜白色高跟鞋| eeuss鲁片一区二区三区在线看| 五月婷婷激情综合网| 国产免费成人在线视频| 欧美疯狂做受xxxx富婆| aaa国产一区| 狂野欧美性猛交blacked| 亚洲猫色日本管| 精品国产凹凸成av人网站| 欧洲精品一区二区| 国产激情一区二区三区四区| 亚洲国产aⅴ成人精品无吗| 欧美国产日韩a欧美在线观看| 欧美情侣在线播放| 91在线视频网址| 国产高清久久久久| 日韩精品成人一区二区在线| 中文字幕在线观看不卡视频| 精品区一区二区| 欧美喷潮久久久xxxxx| 99re8在线精品视频免费播放| 九九热在线视频观看这里只有精品| 日韩理论片网站| 中文乱码免费一区二区 | 91老司机福利 在线| 久久精品国产77777蜜臀| 亚洲成人免费在线观看| 亚洲精品国产一区二区三区四区在线| 久久精品网站免费观看| 日韩欧美国产高清| 91精品国产色综合久久不卡蜜臀 | 麻豆成人在线观看| 亚洲国产一区视频| 亚洲一区影音先锋| 成人免费在线视频| 中文字幕一区二区三区视频| 久久久777精品电影网影网| 欧美精品一区二区三区四区| 精品国产成人系列| 欧美不卡一区二区三区| 日韩精品一区二区三区视频播放 | 欧美日韩一级大片网址| 色哟哟国产精品免费观看| 成人99免费视频| 成人av电影观看| 91性感美女视频| 91天堂素人约啪| 欧美主播一区二区三区美女| 91久久免费观看| 欧美日韩激情一区二区| 欧美一区二区三区四区五区| 欧美一级夜夜爽| 久久久久久毛片| 国产无一区二区| 成人欧美一区二区三区白人 | 日本一区二区久久| 成人免费在线观看入口| 一区二区三区91| 青青青爽久久午夜综合久久午夜| 免费观看成人av| 国产盗摄视频一区二区三区| 成人av电影在线| 欧美最猛黑人xxxxx猛交| 欧美精品v国产精品v日韩精品| 欧美一区二区美女| 精品1区2区在线观看| 中文在线一区二区| 亚洲色图欧美偷拍| 日韩在线a电影| 国产91对白在线观看九色| 色婷婷综合久久久| 91.com在线观看| 国产日产欧美一区| 亚洲第一久久影院| 国产成人免费9x9x人网站视频| 色综合久久天天| 日韩免费电影网站| 中文字幕在线播放不卡一区| 亚洲一二三四区| 国产麻豆精品95视频| 色偷偷成人一区二区三区91| 日韩一区二区三区视频| 亚洲欧美中日韩| 男人操女人的视频在线观看欧美| 久久国产精品99精品国产| 成人av在线网| 日韩欧美黄色影院| 亚洲精品福利视频网站| 国内精品久久久久影院一蜜桃| 91麻豆福利精品推荐| 精品区一区二区| 亚洲一区二区三区激情| 国产精品91xxx| 亚洲六月丁香色婷婷综合久久| 日韩精品免费视频人成| 成人av在线网| 亚洲精品在线一区二区| 亚洲一区二区黄色| eeuss鲁片一区二区三区在线看| 欧美二区乱c少妇| 一区二区三区欧美在线观看| 国内精品伊人久久久久av一坑| 色婷婷综合久久久中文一区二区| xfplay精品久久| 午夜在线成人av| 91免费看`日韩一区二区| 久久久国产精品麻豆| 秋霞影院一区二区| 欧美日韩在线直播| 亚洲猫色日本管| 91一区二区三区在线观看| 久久久久国产一区二区三区四区 | 成人性视频网站| 精品日韩一区二区三区免费视频| 亚洲国产日韩综合久久精品| av电影天堂一区二区在线| 久久精品免费在线观看| 久久99久久精品欧美| 欧美一区二区播放| 五月激情丁香一区二区三区| 在线国产电影不卡| 亚洲欧美区自拍先锋| 成人毛片老司机大片| 久久只精品国产| 国产一区二区在线免费观看| 4438亚洲最大| 男女男精品视频网| 欧美一区二区视频在线观看2022 | 精品乱人伦小说| 精品中文字幕一区二区小辣椒| 91麻豆精品国产91| 欧美aaaaa成人免费观看视频| 7777精品伊人久久久大香线蕉经典版下载 | 国产精品一区二区在线观看不卡| 日韩欧美一区二区三区在线| 日韩电影在线看| 日韩欧美一级片| 国产精一区二区三区| 国产亚洲欧美一级| 风间由美一区二区av101| 国产精品美女视频| 成人av资源在线观看| 亚洲日本乱码在线观看| 色欧美日韩亚洲| 香蕉乱码成人久久天堂爱免费| 欧美精品亚洲一区二区在线播放| 日韩一区欧美二区| 精品国产欧美一区二区| 麻豆精品视频在线观看| 久久色视频免费观看| 国产精品一级二级三级| 136国产福利精品导航| 在线观看区一区二| 麻豆视频一区二区| 欧美激情一区二区三区| 91农村精品一区二区在线| 亚洲.国产.中文慕字在线| 欧美一区二区精美| 成人丝袜18视频在线观看| 亚洲欧美另类综合偷拍| 欧美色中文字幕| 蜜桃精品在线观看| 国产精品久久久久久亚洲毛片 | 欧美专区亚洲专区| 久久精品国产精品亚洲综合| 2020国产精品自拍| 91免费观看在线| 免费不卡在线观看|