第10章-嵌入式Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)_第1頁(yè)
第10章-嵌入式Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)_第2頁(yè)
第10章-嵌入式Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)_第3頁(yè)
第10章-嵌入式Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)_第4頁(yè)
第10章-嵌入式Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)_第5頁(yè)
已閱讀5頁(yè),還剩47頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

2024/1/5Page1第10章嵌入式Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)設(shè)備驅(qū)動(dòng)程序介于操作系統(tǒng)和硬件之間,屏蔽了硬件設(shè)備的物理細(xì)節(jié),并提供了訪問(wèn)各種硬件設(shè)備的統(tǒng)一接口。驅(qū)動(dòng)程序設(shè)計(jì)是嵌入式Linux開(kāi)發(fā)中重要的一局部,也是比較困難的一局部,在進(jìn)行這局部的開(kāi)發(fā)時(shí)需要熟悉Linux的內(nèi)核機(jī)制、驅(qū)動(dòng)程序與用戶級(jí)應(yīng)用程序的接口,需要考慮系統(tǒng)對(duì)設(shè)備的并發(fā)操作,需要非常熟悉所開(kāi)發(fā)硬件的工作原理。2024/1/5Page2第10章嵌入式Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述10.1設(shè)備驅(qū)動(dòng)模塊化編程10.2Linux字符設(shè)備驅(qū)動(dòng)10.3塊設(shè)備驅(qū)動(dòng)10.42024/1/5Page3第10章嵌入式Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)

本章小結(jié)10.6思考與練習(xí)10.7網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)10.52024/1/5Page410.1Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述

操作系統(tǒng)的目的之一就是掩蓋掉各種硬件的特殊性,使得系統(tǒng)中的硬件設(shè)備對(duì)于用戶而言是透明的。用來(lái)管理硬件控制器的軟件通常叫做設(shè)備驅(qū)動(dòng)程序。Linux驅(qū)動(dòng)程序功能是對(duì)設(shè)備初始化和釋放、把數(shù)據(jù)從內(nèi)核傳送到硬件和從硬件讀取數(shù)據(jù)、讀取應(yīng)用程序傳送給設(shè)備文件的數(shù)據(jù)和回送應(yīng)用程序請(qǐng)求的數(shù)據(jù)、檢測(cè)和處理設(shè)備出現(xiàn)的錯(cuò)誤。Linux核心的設(shè)備驅(qū)動(dòng)程序根本上是一些共享庫(kù)(SharedLibrary),在庫(kù)中含有一些用來(lái)處理底層硬件的例程。Linux的設(shè)備驅(qū)動(dòng)程序用來(lái)處理各種硬件的多樣性。操作系統(tǒng)的根本功能之一是對(duì)設(shè)備處理的抽象化。所有的物理設(shè)備被當(dāng)做正規(guī)的文件來(lái)處理,可以被“翻開(kāi)〞、“關(guān)閉〞、“讀〞和“寫(xiě)〞,就像用系統(tǒng)調(diào)用處理文件一樣。系統(tǒng)中每一個(gè)設(shè)備都對(duì)應(yīng)一個(gè)設(shè)備特殊文件,例如,系統(tǒng)中的第一個(gè)IDE磁盤(pán)的設(shè)備文件名是/dev/hda。對(duì)于塊設(shè)備(如磁盤(pán))和字符設(shè)備,它們的的設(shè)備特殊文件通常是通過(guò)mknod命令用主設(shè)備號(hào)和次設(shè)備號(hào)來(lái)描述和創(chuàng)立的。2024/1/5Page510.1Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)調(diào)試有兩種方法:一種是直接編譯到內(nèi)核,隨同Linux啟動(dòng)時(shí)加載,啟動(dòng)內(nèi)核時(shí)就會(huì)驅(qū)動(dòng)此硬件設(shè)備。這種方法稱為靜態(tài)鏈接。另一種是編譯為可加載模塊〔Loadablekernelmodules〕的形式,編譯生成一個(gè).o文件,當(dāng)應(yīng)用程序需要時(shí)再動(dòng)態(tài)加載進(jìn)內(nèi)核空間運(yùn)行,這種方法稱為動(dòng)態(tài)鏈接。Linux提供了一批管理內(nèi)核模塊的命令,主要有1smod、insmod和rmmod等。1smod命令用于查看當(dāng)前內(nèi)核加載的模塊信息;insmod命令將編譯的模塊直接插入內(nèi)核,如果出現(xiàn)故障,可以使用rmmod命令從內(nèi)核卸載模塊,而不需要重新啟動(dòng)內(nèi)核。2024/1/5Page610.1Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述2024/1/5Page710.1Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述設(shè)備驅(qū)動(dòng)和文件系統(tǒng)的關(guān)系設(shè)備驅(qū)動(dòng)程序的任務(wù)包括自動(dòng)配置和初始化子程序,負(fù)責(zé)檢測(cè)所要驅(qū)動(dòng)的硬件設(shè)備是否存在和是否能正常工作。如果該設(shè)備正常,那么對(duì)這個(gè)設(shè)備及其相關(guān)的設(shè)備驅(qū)動(dòng)程序需要的軟件狀態(tài)進(jìn)行初始化。這局部驅(qū)動(dòng)程序僅在初始化的時(shí)候被調(diào)用一次。10.1Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述效勞于I/O請(qǐng)求的子程序,又稱為驅(qū)動(dòng)程序的上半局部。調(diào)用這局部是系統(tǒng)調(diào)用的結(jié)果。在執(zhí)行這局部程序的時(shí)候,系統(tǒng)仍認(rèn)為和進(jìn)行調(diào)用的進(jìn)程屬于同一個(gè)進(jìn)程,只是由用戶態(tài)轉(zhuǎn)換為核心態(tài),并具有進(jìn)行此系統(tǒng)調(diào)用的用戶程序的運(yùn)行環(huán)境,所以可以在其中調(diào)用sleep()等與進(jìn)程運(yùn)行環(huán)境有關(guān)的函數(shù)。在系統(tǒng)內(nèi)部,I/O設(shè)備的存取通過(guò)一組固定的入口點(diǎn)來(lái)進(jìn)行,這組入口點(diǎn)是由每個(gè)設(shè)備的設(shè)備驅(qū)動(dòng)程序提供的。設(shè)備驅(qū)動(dòng)和文件系統(tǒng)的關(guān)系2024/1/5Page810.1Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述10.1.2設(shè)備類型和設(shè)備號(hào)

1.字符設(shè)備2.塊設(shè)備3.網(wǎng)絡(luò)設(shè)備2024/1/5Page910.1Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述1.字符設(shè)備一個(gè)字符設(shè)備是一種字節(jié)流設(shè)備,對(duì)設(shè)備的存取只能按順序按字節(jié)的存取而不能隨機(jī)訪問(wèn),字符設(shè)備沒(méi)有請(qǐng)求緩沖區(qū),所有的訪問(wèn)請(qǐng)求都是按順序執(zhí)行的。Linux下的大多設(shè)備都是字符設(shè)備。應(yīng)用程序是通過(guò)字符設(shè)備節(jié)點(diǎn)來(lái)訪問(wèn)字符設(shè)備的。設(shè)備節(jié)點(diǎn)一般都由mknod命令創(chuàng)立在/dev目錄下,字符設(shè)備文件的第一個(gè)標(biāo)志是前面的“c〞標(biāo)志。如“crw-rw〞、“crw-r〞“crw-rw〞所代表的文件都是字符設(shè)備文件。2024/1/5Page1010.1Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述1.字符設(shè)備Linux使用管理文件的方法來(lái)管理字符設(shè)備,所以每個(gè)字符設(shè)備在/dev/目錄下都有一個(gè)對(duì)應(yīng)的設(shè)備文件,即設(shè)備節(jié)點(diǎn),它們包含了設(shè)備的類型、主/次設(shè)備號(hào)以及設(shè)備的訪問(wèn)權(quán)限控制等。每個(gè)字符設(shè)備文件都有自己的與普通文件相同的文件操作函數(shù)組結(jié)構(gòu)〔structfile_operations〕。字符設(shè)備驅(qū)動(dòng)通常至少需要實(shí)現(xiàn)文件操作函數(shù)組中的open()、release()、read()和write()四種操作方法。常見(jiàn)的字符設(shè)備有鼠標(biāo)、鍵盤(pán)等。2024/1/5Page112.塊設(shè)備存儲(chǔ)設(shè)備一般屬于塊設(shè)備,塊設(shè)備有請(qǐng)求緩沖區(qū),并且支持隨機(jī)訪問(wèn)而不必按照順序去存取數(shù)據(jù)。Linux下的磁盤(pán)設(shè)備都是塊設(shè)備,盡管在Linux下有塊設(shè)備節(jié)點(diǎn),但應(yīng)用程序一般是通過(guò)文件系統(tǒng)及其高速緩存來(lái)訪問(wèn)塊設(shè)備的,而不是直接通過(guò)設(shè)備節(jié)點(diǎn)來(lái)讀寫(xiě)塊設(shè)備上的數(shù)據(jù)。塊設(shè)備文件的第一個(gè)標(biāo)志是前面的“b〞標(biāo)志,如“brw-rw〞所代表的就是塊設(shè)備。10.1Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述2024/1/5Page122.塊設(shè)備塊設(shè)備既可以作為普通的設(shè)備用來(lái)存放任意數(shù)據(jù),也可以將塊設(shè)備按某種文件系統(tǒng)類型的格式進(jìn)行格式化,然后按照該文件系統(tǒng)類型的格式來(lái)讀取塊設(shè)備上的數(shù)據(jù),但不管哪種方式,最后訪問(wèn)設(shè)備上的數(shù)據(jù)都必須通過(guò)調(diào)用設(shè)備本身的操作方法實(shí)現(xiàn),區(qū)別在于前者直接調(diào)用塊設(shè)備的操作方法,而后者那么間接調(diào)用塊設(shè)備的操作方法。常見(jiàn)的塊設(shè)備有各種硬盤(pán)、flash磁盤(pán)、RAM磁盤(pán)等。10.1Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述2024/1/5Page133.網(wǎng)絡(luò)設(shè)備網(wǎng)絡(luò)設(shè)備不同于字符設(shè)備和塊設(shè)備,它是面向報(bào)文的而不是面向流的,它不支持隨機(jī)訪問(wèn),也沒(méi)有請(qǐng)求緩沖區(qū)。在Linux里一個(gè)網(wǎng)絡(luò)設(shè)備也可以叫做一個(gè)網(wǎng)絡(luò)接口,應(yīng)用程序是通過(guò)Socket而不是設(shè)備節(jié)點(diǎn)來(lái)訪問(wèn)網(wǎng)絡(luò)設(shè)備,在系統(tǒng)里根本就不存在網(wǎng)絡(luò)設(shè)備節(jié)點(diǎn)。內(nèi)核使用一套與數(shù)據(jù)包傳輸相關(guān)的函數(shù)來(lái)與網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序通信,它們不同于字符設(shè)備和塊設(shè)備的read()和write()方法。10.1Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述2024/1/5Page143.網(wǎng)絡(luò)設(shè)備Linux系統(tǒng)通過(guò)設(shè)備號(hào)來(lái)區(qū)分不同設(shè)備。設(shè)備號(hào)由兩局部組成:主設(shè)備號(hào)和次設(shè)備號(hào)。主設(shè)備號(hào)指明對(duì)應(yīng)哪些設(shè)備驅(qū)動(dòng),這種對(duì)應(yīng)關(guān)系是固定不變的并作為內(nèi)核資源的一局部存在。需要注意的是,同一個(gè)主設(shè)備號(hào)可以對(duì)應(yīng)兩個(gè)不同的設(shè)備驅(qū)動(dòng),一個(gè)可以是字符設(shè)備另一個(gè)可以是塊設(shè)備。10.1Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述2024/1/5Page153.網(wǎng)絡(luò)設(shè)備次設(shè)備號(hào)區(qū)分被一個(gè)設(shè)備驅(qū)動(dòng)控制下的某個(gè)獨(dú)立的設(shè)備。比方,同一個(gè)類型的USB設(shè)備可以在系統(tǒng)中存在幾個(gè),它們通過(guò)次設(shè)備號(hào)加以區(qū)分,而設(shè)備驅(qū)動(dòng)可以只對(duì)應(yīng)一個(gè)。Linux支持的各種設(shè)備的主設(shè)備號(hào)定義在include/linux/major.h文件中,而已經(jīng)在官方注冊(cè)的主設(shè)備號(hào)和次設(shè)備號(hào)在Documentation/devices.txt文件中可以找到。10.1Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)概述2024/1/5Page16模塊是程序設(shè)計(jì)中一個(gè)十分重要的概念,它是一個(gè)具有獨(dú)立邏輯功能的代碼塊,每個(gè)模塊都可以被重復(fù)使用,模塊化編程可以有效提高程序的編寫(xiě)效率,同時(shí)也能增強(qiáng)程序的可讀性和易修改性。10.2設(shè)備驅(qū)動(dòng)模塊化編程2024/1/5Page172024/1/5Page1810.2設(shè)備驅(qū)動(dòng)模塊化編程10.2.1設(shè)備驅(qū)動(dòng)程序原理Linux設(shè)備驅(qū)動(dòng)程序主要由驅(qū)動(dòng)程序的注冊(cè)與注銷、設(shè)備的翻開(kāi)與釋放、設(shè)備的讀寫(xiě)操作、設(shè)備的控制操作、設(shè)備的中斷和輪詢處理等局部組成,每個(gè)局部都有與之對(duì)應(yīng)的接口。10.2設(shè)備驅(qū)動(dòng)模塊化編程10.2.1設(shè)備驅(qū)動(dòng)程序原理

Linux內(nèi)核在結(jié)構(gòu)體file_operations中統(tǒng)一定義了設(shè)備文件的各個(gè)訪問(wèn)接口,file_operations結(jié)構(gòu)定義在/include/linux/fs.h中。設(shè)備驅(qū)動(dòng)程序加載時(shí),首先會(huì)在內(nèi)核中注冊(cè)對(duì)應(yīng)的設(shè)備號(hào)和結(jié)構(gòu)體file_operations。應(yīng)用程序通過(guò)系統(tǒng)調(diào)用訪問(wèn)設(shè)備時(shí),內(nèi)核會(huì)根據(jù)設(shè)備號(hào)查找到相應(yīng)的結(jié)構(gòu)體file_operations,然后再根據(jù)結(jié)構(gòu)體file_operations中的接口調(diào)用具體放入設(shè)備訪問(wèn)函數(shù)。2024/1/5Page192024/1/5Page2010.2設(shè)備驅(qū)動(dòng)模塊化編程10.2.2設(shè)備訪問(wèn)方式及實(shí)現(xiàn)設(shè)備訪問(wèn)方式有多種,選擇哪種訪問(wèn)方式不僅與設(shè)備本身有關(guān),還與它的使用情況有關(guān)。Linux對(duì)查詢方式、中斷方式和DMA三種方式都提供了很好的支持。10.2.2設(shè)備訪問(wèn)方式及實(shí)現(xiàn)1、查詢方式在數(shù)據(jù)傳送之前,對(duì)目標(biāo)設(shè)備的狀態(tài)進(jìn)行查詢,確知外設(shè)已經(jīng)做好了傳送數(shù)據(jù)的準(zhǔn)備時(shí)再進(jìn)行數(shù)據(jù)傳送,否那么,CPU等待并持續(xù)不斷的查詢,一旦外設(shè)準(zhǔn)備好,那么立即進(jìn)行讀或?qū)懖僮?,這種方式稱為查詢方式。10.2設(shè)備驅(qū)動(dòng)模塊化編程2024/1/5Page2110.2設(shè)備驅(qū)動(dòng)模塊化編程1、查詢方式對(duì)于查詢方式來(lái)說(shuō),一個(gè)數(shù)據(jù)傳送過(guò)程由三個(gè)環(huán)節(jié)組成:(1)從接口中讀取狀態(tài)字。(2)CPU檢測(cè)狀態(tài)字的對(duì)應(yīng)位是否滿足就緒條件,如果不滿足,那么回到前一步,繼續(xù)讀取狀態(tài)字。(3)如果狀態(tài)字說(shuō)明外設(shè)己處于就緒狀態(tài),那么傳送數(shù)據(jù)。這種方式看上去似乎很浪費(fèi)資源,效率低,但在某些情況下仍有使用的價(jià)值。例如當(dāng)一個(gè)設(shè)備從翻開(kāi)計(jì)算機(jī)到關(guān)閉之前一直需要使用,而它又沒(méi)有向系統(tǒng)發(fā)中斷的功能,這種場(chǎng)合下查詢方式還是很有用的。在Linux驅(qū)動(dòng)程序中實(shí)現(xiàn)這種方式還是比較簡(jiǎn)單的。只要在驅(qū)動(dòng)程序的read()程序中使用while語(yǔ)句一直判斷外設(shè)的狀態(tài),狀態(tài)一旦滿足要求,那么跳出循環(huán),讀取外設(shè)數(shù)據(jù)并返回read()函數(shù)就可以了。2024/1/5Page222、中斷方式在中斷傳送方式下,外設(shè)具有申請(qǐng)CPU效勞的主動(dòng)權(quán),當(dāng)輸入設(shè)備已將數(shù)據(jù)準(zhǔn)備好或者輸出設(shè)備可以接收數(shù)據(jù)時(shí),便可以向CPU發(fā)出中斷請(qǐng)求,使CPU暫時(shí)停下目前的工作而和外設(shè)進(jìn)行一次數(shù)據(jù)傳輸,等輸入操作完成后,CPU繼續(xù)進(jìn)行原來(lái)的工作??梢?jiàn)中斷傳送方式就是外部設(shè)備中斷CPU的工作,使CPU停止執(zhí)行當(dāng)前程序,而去執(zhí)行一個(gè)為外部設(shè)備的數(shù)據(jù)輸入輸出效勞程序,該效勞程序稱為中斷處理子程序或中斷效勞子程序。中斷子程序執(zhí)行完后,CPU又轉(zhuǎn)回來(lái)執(zhí)行原來(lái)的程序。被外界中斷時(shí),程序中下一條指令所在處稱為斷點(diǎn),從中斷效勞程序返回時(shí),從斷點(diǎn)處繼續(xù)執(zhí)行被中斷的程序。10.2設(shè)備驅(qū)動(dòng)模塊化編程2024/1/5Page232、中斷方式采用這方式訪問(wèn)外設(shè)的前提是該外設(shè)能發(fā)出操作系統(tǒng)能識(shí)別的中斷。在Linux驅(qū)動(dòng)程序中采用中斷方式訪問(wèn)外設(shè)需做到以下幾點(diǎn):(1)向系統(tǒng)申請(qǐng)中斷。Linux提供了函數(shù)request_irq()來(lái)實(shí)現(xiàn)申請(qǐng)中斷。申請(qǐng)成功與否的關(guān)鍵在于此函數(shù)的一個(gè)參數(shù)irq,它是希望申請(qǐng)的中斷號(hào)。如果外設(shè)可以發(fā)中斷,那該參數(shù)就填2。不過(guò)還有一點(diǎn)需要考慮的是如果想申請(qǐng)的中斷號(hào)己被別的設(shè)備占用,那就需要想方法協(xié)調(diào)這兩個(gè)設(shè)備了??梢允褂妹頲at/proc/interrupts來(lái)查看操作系統(tǒng)中現(xiàn)有中斷號(hào)的使用情況。當(dāng)然是否申請(qǐng)成功,也可以通過(guò)這條命令查看。(2)釋放中斷。函數(shù)free_irq()可以實(shí)現(xiàn)這個(gè)功能。(3)實(shí)現(xiàn)中斷函數(shù)。申請(qǐng)完中斷號(hào)以后,希望系統(tǒng)響應(yīng)該中斷后做些什么全依賴此函數(shù)。其實(shí)該函數(shù)也沒(méi)有特別的地方,無(wú)非就是做些讀寫(xiě)設(shè)備的動(dòng)作,采集需要的數(shù)據(jù)。不過(guò)需要說(shuō)明的是該函數(shù)應(yīng)該盡量的短,因?yàn)榇藭r(shí)在獨(dú)占CPU資源,系統(tǒng)很難響應(yīng)別的事件。該函數(shù)的末尾應(yīng)該調(diào)用函數(shù)wake_up_interruptible(),來(lái)喚醒該設(shè)備隊(duì)列中其它進(jìn)程。10.2設(shè)備驅(qū)動(dòng)模塊化編程2024/1/5Page243、DMA方式在DMA方式下,外部設(shè)備利用專門(mén)的接口電路直接和存儲(chǔ)器進(jìn)行數(shù)據(jù)傳送,并不經(jīng)過(guò)CPU。這樣,進(jìn)行傳輸就不必進(jìn)行保護(hù)現(xiàn)場(chǎng)之類的一系列額外操作,數(shù)據(jù)傳輸?shù)乃俣雀旧蠜Q定于外設(shè)和存儲(chǔ)器的速度。DMA方式傳送數(shù)據(jù)那么由DMA控制器來(lái)提供源和目的地址、修改地址、控制結(jié)束及發(fā)出控制信號(hào)。顯然,采用DMA方式,數(shù)據(jù)傳送的速度顯著提高,而且CPU的負(fù)擔(dān)也明顯減輕了。同時(shí)也縮短了傳送的響應(yīng)時(shí)間。10.2.2設(shè)備訪問(wèn)方式及實(shí)現(xiàn)2024/1/5Page253、DMA方式DMA傳送的根本過(guò)程如下:(1)外部設(shè)備(或CPU利用指令)向DMA控制器發(fā)出DMA傳送請(qǐng)求。(2)DMAC向CPU發(fā)總線請(qǐng)求,要求CPU交出總線的管理和使用權(quán),并在接到CPU的總線響應(yīng)信號(hào)后接管系統(tǒng)總線的管理和使用權(quán),從而變?yōu)橄到y(tǒng)的主設(shè)備。(3)DMAC將被訪問(wèn)存儲(chǔ)單元地址送到地址總線上。(4)向存儲(chǔ)器和進(jìn)行DMA傳送的外設(shè)發(fā)出讀寫(xiě)命令,那么存儲(chǔ)器和外設(shè)通過(guò)數(shù)據(jù)總線進(jìn)行數(shù)據(jù)傳送。(5)假設(shè)DMA傳送己完成,那么DMAC撤銷對(duì)CPU的總線請(qǐng)求,交回系統(tǒng)總線的管理和使用權(quán),回到從設(shè)備狀態(tài)。10.2.2設(shè)備訪問(wèn)方式及實(shí)現(xiàn)2024/1/5Page262024/1/5Page2710.2設(shè)備驅(qū)動(dòng)模塊化編程10.2.3內(nèi)核與驅(qū)動(dòng)程序的關(guān)系操作系統(tǒng)中分為單體內(nèi)核〔Monolithickernel〕和微內(nèi)核〔Microkernel〕兩種,單體內(nèi)核是一個(gè)相對(duì)較大的程序,而微內(nèi)核是一個(gè)較小的程序,操作系統(tǒng)的大局部功能運(yùn)行在用戶空間。Linux是一個(gè)單體內(nèi)核,分成5個(gè)子系統(tǒng),整個(gè)內(nèi)核在一個(gè)地址空間。這樣增加一個(gè)設(shè)備就比較麻煩,由于設(shè)備需要在內(nèi)核空間運(yùn)行,因此需要重新編譯內(nèi)核。Linux通過(guò)使用內(nèi)核可以根據(jù)需要將各局部放入內(nèi)核。10.2.3內(nèi)核與驅(qū)動(dòng)程序的關(guān)系應(yīng)用程序、庫(kù)、內(nèi)核、驅(qū)動(dòng)程序的關(guān)系框圖如圖10-2所示:2024/1/5Page282024/1/5Page2910.2設(shè)備驅(qū)動(dòng)模塊化編程10.2.4中斷處理中斷處理是設(shè)備驅(qū)動(dòng)程序的根本功能之一。Linux內(nèi)核對(duì)所有的中斷進(jìn)行了統(tǒng)一編號(hào),并把中斷的相關(guān)信息存儲(chǔ)在結(jié)構(gòu)體數(shù)組irq_desc中。該數(shù)組定義在/include/linux/irq.h中。每個(gè)數(shù)組元素對(duì)應(yīng)一個(gè)中斷,其中包含中斷名、中斷狀態(tài)和硬件訪問(wèn)函數(shù)以及中斷處理函數(shù)的入口地址等信息。2024/1/5Page3010.3Linux字符設(shè)備驅(qū)動(dòng)ARM處理器的應(yīng)用領(lǐng)域Linux字符設(shè)備驅(qū)動(dòng)框架如下: 定義一個(gè)結(jié)構(gòu)體staticstructfile_operations變量,其內(nèi)定義一些設(shè)備的翻開(kāi)、關(guān)閉、讀、寫(xiě)、控制函數(shù); 在結(jié)構(gòu)體外分別實(shí)現(xiàn)結(jié)構(gòu)體中定義的這些函數(shù); 向內(nèi)核中注冊(cè)或刪除驅(qū)動(dòng)模塊。字符設(shè)備驅(qū)動(dòng)程序的框架的核心是數(shù)據(jù)結(jié)構(gòu)structfile_operation,它是一系列指針的集合,每個(gè)被翻開(kāi)的文件都對(duì)應(yīng)于一系列的操作,需要在驅(qū)動(dòng)程序中加以實(shí)現(xiàn)。其定義如下〔在/include/linux/fs.h中定義〕:structfile_operations{int(*seek)(structinode*,structfile*,off_t,int);int(*read)(structinode*,structfile*,char,int);int(*write)(structinode*,structfile*,off_t,int);int(*readdir)(structinode*,structfile*,structdirent*,int);int(*select)(structinode*,structfile*,int,select_table*);int(*ioctl)(structinode*,structfile*,unsinedint,unsignedlong);int(*mmap)(structinode*,structfile*,structvm_area_struct*);int(*open)(structinode*,structfile*);int(*release)(structinode*,structfile*);int(*fsync)(structinode*,structfile*);int(*fasync)(structinode*,structfile*,int);int(*check_media_change)(structinode*,structfile*);int(*revalidate)(dev_tdev);}10.3Linux字符設(shè)備驅(qū)動(dòng)2024/1/5Page31塊設(shè)備接口主要是針對(duì)硬盤(pán)、軟盤(pán)、CD-ROM等慢速設(shè)備設(shè)計(jì)的,以免消耗過(guò)多的CPU等待時(shí)間。它僅僅支持面向塊的I/O操作,所有I/O操作都通過(guò)在內(nèi)核地址空間中的I/O緩沖區(qū)進(jìn)行。當(dāng)多個(gè)請(qǐng)求同時(shí)提交給設(shè)備時(shí),塊設(shè)備訪問(wèn)的性能很大程度上取決于請(qǐng)求的順序。由于塊設(shè)備有可移動(dòng)的單元,如果所有的請(qǐng)求是朝著同一個(gè)方向的,性能最正確。10.4塊設(shè)備驅(qū)動(dòng)2024/1/5Page32塊設(shè)備驅(qū)動(dòng)程序的特點(diǎn)如下:1、塊設(shè)備接口相對(duì)復(fù)雜,不如字符設(shè)備明晰易用。2、塊設(shè)備驅(qū)動(dòng)程序?qū)φ麄€(gè)系統(tǒng)的性能影響較大,速度和效率是需要考慮的重要方面。3、系統(tǒng)中使用緩沖區(qū)與訪問(wèn)請(qǐng)求的優(yōu)化管理來(lái)提高系統(tǒng)的性能。10.4塊設(shè)備驅(qū)動(dòng)2024/1/5Page3410.4塊設(shè)備驅(qū)動(dòng)10.4.1塊設(shè)備驅(qū)動(dòng)簡(jiǎn)介塊設(shè)備〔blockdevice〕是文件系統(tǒng)的物質(zhì)根底,它也支持像文件一樣被訪問(wèn)。這種為翻開(kāi)的塊特殊文件提供正確的文件操作組的機(jī)制和字符設(shè)備的十分相似。Linux用blkdevs向量表維護(hù)已經(jīng)登記的塊設(shè)備文件。它像chrdevs向量表一樣,使用設(shè)備的主設(shè)備號(hào)作為索引。它的條目也是device_struct數(shù)據(jù)結(jié)構(gòu)。與字符設(shè)備不同,塊設(shè)備進(jìn)行分類,SCSI是其中一類,而IDE是另一類。2024/1/5Page3510.4塊設(shè)備驅(qū)動(dòng)10.4.2塊設(shè)備相關(guān)結(jié)構(gòu)體1.structblock_device_operations結(jié)構(gòu)體2.structgendisk結(jié)構(gòu)體3.structrequest_queue結(jié)構(gòu)體4.structhd_struct結(jié)構(gòu)體5.structbio結(jié)構(gòu)體6.structblock_device結(jié)構(gòu)體

10.4塊設(shè)備驅(qū)動(dòng)structblock_device_operations結(jié)構(gòu)體塊設(shè)備通過(guò)structblock_device_operations結(jié)構(gòu)使它們的操作對(duì)系統(tǒng)可用,定義在/include/linux/fs.h中。structblock_device_operations{int(*open)(structinode*,structfile*);/*翻開(kāi)設(shè)備*/int(*release)(structinode*,structfile*);/*釋放*/int(*ioctl)(structinode*,structfile*,unsigned,unsignedlong);/*ioct1系統(tǒng)調(diào)用的實(shí)現(xiàn)*/long(*unlocked_ioctl)(structfile*,unsigned,unsignedlong);long(*compat_ioctl)(structfile*,unsigned,unsignedlong);int(*direct_access)(structblock_device*,sector_t,unsignedlong*);int(*media_changed)(structgendisk*);/*用于檢查驅(qū)動(dòng)器介質(zhì)是否改變*/int(*revalidate_disk)(structgendisk*);/*使介質(zhì)有效*/int(*getgeo)(structblock_device*,structhd_geometry*);/*填充驅(qū)動(dòng)器信息*/structmodule*owner;/*模塊擁有者*/};2024/1/5Page362.structgendisk結(jié)構(gòu)體Linux內(nèi)核中,使用structgendisk結(jié)構(gòu)體來(lái)表示一個(gè)獨(dú)立的磁盤(pán)設(shè)備或者分區(qū)。structgendisk{intmajor;/*主設(shè)備號(hào)*/intfirst_minor;/*第1個(gè)次設(shè)備號(hào)*/intminors;/*最大次設(shè)備號(hào)數(shù)量,如果設(shè)備不能分區(qū),該值為1*/chardisk_name[32];/*主設(shè)備名*/structhd_struct**part;/*分區(qū)信息*/intpart_uevent_suppress;structblock_device_operations*fops;/*設(shè)備操作結(jié)構(gòu)體*/structrequest_queue*queue;/*設(shè)備請(qǐng)求隊(duì)列*/void*private_data;/*私有數(shù)據(jù)*/sector_tcapacity;/*扇區(qū)數(shù)*/intflags;/*設(shè)置驅(qū)動(dòng)器狀態(tài)的標(biāo)志*/chardevfs_name[64];intnumber;structdevice*driverfs_dev;structkobjectkobj;10.4塊設(shè)備驅(qū)動(dòng)2024/1/5Page373.structrequest_queue結(jié)構(gòu)體structrequest_queue結(jié)構(gòu)體表征等待進(jìn)行的請(qǐng)求隊(duì)列。structrequest_queue{structlist_headqueue_head;structrequest*last_merge;

elevator_televator;

request_fn_proc*request_fn;merge_request_fn*back_merge_fn;merge_request_fn*front_merge_fn;merge_requests_fn*merge_requests_fn;make_request_fn*make_request_fn;prep_rq_fn*prep_rq_fn;unplug_fn*unplug_fn;merge_bvec_fn*merge_bvec_fn;activity_fn*activity_fn;structtimer_listunplug_timer;intunplug_thresh;unsignedlongunplug_delay;

structwork_structunplug_work;structbacking_dev_infobacking_dev_info;}10.4塊設(shè)備驅(qū)動(dòng)2024/1/5Page384.structhd_struct結(jié)構(gòu)體該結(jié)構(gòu)體存儲(chǔ)了磁盤(pán)上的分區(qū)信息。structhd_struct{sector_tstart_sect;sector_tnr_sects;structkobjectkobj;unsignedreads,read_sectors,writes,write_sectors;intpolicy,partno;}

10.4塊設(shè)備驅(qū)動(dòng)2024/1/5Page395.structbio結(jié)構(gòu)體該結(jié)構(gòu)用來(lái)描述內(nèi)核以文件系統(tǒng)、虛擬內(nèi)存子系統(tǒng)或系統(tǒng)調(diào)用的形式對(duì)塊I/O設(shè)備進(jìn)行的輸入、輸出數(shù)據(jù)的操作。structbio{sector_tbi_sector;structbio*bi_next;/*請(qǐng)求隊(duì)列鏈表*/structblock_device*bi_bdev;unsignedlongbi_flags;/*狀態(tài)、命令等*/unsignedlongbi_rw;unsignedshortbi_vcnt;/*bio_vec的個(gè)數(shù)*/unsignedshortbi_idx;/*bvl_vec的當(dāng)前索引*/unsignedshortbi_phys_segments;unsignedshortbi_hw_segments;unsignedintbi_size;/*剩余I/O數(shù)量*/unsignedintbi_hw_front_size;unsignedintbi_hw_back_size;unsignedintbi_max_vecs;/*最多可持有的bvl_vecs數(shù)量*/structbio_vec*bi_io_vec;/*實(shí)際的矢量表*/bio_end_io_t*bi_end_io;atomic_tbi_cnt;void*bi_private;bio_destructor_t*bi_destructor;/*銷毀器*/};10.4塊設(shè)備驅(qū)動(dòng)2024/1/5Page406.structblock_device結(jié)構(gòu)體這個(gè)結(jié)構(gòu)代表了內(nèi)核中的一個(gè)設(shè)備,它可以表示整個(gè)磁盤(pán)或者一個(gè)特定的分區(qū)。當(dāng)這個(gè)結(jié)構(gòu)代表一個(gè)分區(qū)時(shí),bd_contains指向包含這個(gè)分區(qū)的設(shè)備,bd_part指向設(shè)備的分區(qū)結(jié)構(gòu)。當(dāng)這個(gè)結(jié)構(gòu)代表一個(gè)塊設(shè)備時(shí),bd_disk指向設(shè)備的gendisk結(jié)構(gòu)。structblock_device{dev_tbd_dev;structinode*bd_inode;/*分區(qū)節(jié)點(diǎn)*/intbd_openers;structsemaphorebd_sem;/*翻開(kāi)/關(guān)閉鎖*/structsemaphorebd_mount_sem;/*加載互斥鎖*/structlist_headbd_inodes;void*bd_holders;intbd_holders;}10.4塊設(shè)備驅(qū)動(dòng)2024/1/5Page41Linux系統(tǒng)具有比較完善的網(wǎng)絡(luò)功能,Linux網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)是Linux網(wǎng)絡(luò)應(yīng)用的重要組成局部。在Linux網(wǎng)絡(luò)系統(tǒng)中,其網(wǎng)絡(luò)子系統(tǒng)主要是基于BSDunix的socket機(jī)制。在網(wǎng)絡(luò)子系統(tǒng)和驅(qū)動(dòng)程序之間定義了專門(mén)的數(shù)據(jù)結(jié)構(gòu)sk_buff進(jìn)行數(shù)據(jù)傳遞。Linux系統(tǒng)提供支持對(duì)發(fā)送數(shù)據(jù)和接收數(shù)據(jù)的緩存,提供流量控制機(jī)制,提供對(duì)多協(xié)議的支持。網(wǎng)絡(luò)接口在內(nèi)核層處理包的發(fā)送和接收,并不存在于進(jìn)程中的Linux文件系統(tǒng)中。網(wǎng)絡(luò)接口在文件系統(tǒng)中的角色就像被掛載的塊設(shè)備,在內(nèi)核中用device數(shù)據(jù)結(jié)構(gòu)來(lái)表示,在做數(shù)據(jù)包的發(fā)送和接收時(shí)直接通過(guò)接口訪問(wèn),不需要進(jìn)行文件的操作。網(wǎng)絡(luò)驅(qū)動(dòng)程序和內(nèi)核之間的交互一次處理一個(gè)網(wǎng)絡(luò)包,這允許協(xié)議可以對(duì)驅(qū)動(dòng)程序隱藏,而物理傳輸可以對(duì)協(xié)議隱藏。10.5網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)2024/1/5Page42Linux網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)層次結(jié)構(gòu)為:1、網(wǎng)絡(luò)協(xié)議接口層2、網(wǎng)絡(luò)設(shè)備接口層3、設(shè)備驅(qū)動(dòng)功能層4、網(wǎng)絡(luò)設(shè)備與媒介層10.5網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)2024/1/5Page432024/1/5Page4410.5網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)10.5.1網(wǎng)絡(luò)設(shè)備概述

常用的網(wǎng)絡(luò)設(shè)備有中繼器、網(wǎng)橋、路由器和網(wǎng)關(guān)。中繼器是局域網(wǎng)互連的最簡(jiǎn)單設(shè)備,它工作在OSI體系結(jié)構(gòu)的物理層,接收并識(shí)別網(wǎng)絡(luò)信號(hào),然后再生信號(hào)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 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ì)用戶上傳內(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)論