版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)設(shè)備驅(qū)動(dòng)開(kāi)發(fā)2010.3提綱提綱n 設(shè)備驅(qū)動(dòng)概述n 如何編寫(xiě)內(nèi)核模塊n 如何編寫(xiě)設(shè)備驅(qū)動(dòng)n 字符設(shè)備驅(qū)動(dòng)實(shí)例預(yù)備知識(shí):設(shè)備控制器的功能及接口預(yù)備知識(shí):設(shè)備控制器的功能及接口n 每一個(gè)物理設(shè)備都有自己的硬件控制器,每一個(gè)硬件控制器都有自己的控制和狀態(tài)寄存器(CSR),不同的設(shè)備是不同的;n 設(shè)備控制器的功能:命令寄存器和譯碼器(接收和識(shí)別命令)、數(shù)據(jù)寄存器(數(shù)據(jù)交換)、狀態(tài)寄存器(設(shè)備狀態(tài)的了解和報(bào)告)、地址寄存器(地址識(shí)別)n 設(shè)備控制器與CPU的接口:數(shù)據(jù)線(xiàn)、地址線(xiàn)、控制線(xiàn)n 設(shè)備控制器與設(shè)備的接口:數(shù)據(jù)信號(hào)、狀態(tài)信號(hào)、控制信號(hào)預(yù)備知識(shí):系統(tǒng)對(duì)設(shè)備的管理預(yù)備知識(shí):系統(tǒng)對(duì)
2、設(shè)備的管理n 設(shè)備控制表(DCT):每個(gè)設(shè)備一張表,表結(jié)構(gòu)如下:設(shè)備標(biāo)識(shí)符、設(shè)備類(lèi)型、設(shè)備地址或設(shè)備號(hào)、設(shè)備狀態(tài)、等待隊(duì)列指針、重復(fù)執(zhí)行的次數(shù)和時(shí)間、I/O控制器指針n 系統(tǒng)設(shè)備表(SDT):整個(gè)系統(tǒng)一張表,表結(jié)構(gòu)如下:DCT指針、正在使用設(shè)備的進(jìn)程標(biāo)識(shí)、設(shè)備驅(qū)動(dòng)程序入口驅(qū)動(dòng)原理:什么是設(shè)備驅(qū)動(dòng)?驅(qū)動(dòng)原理:什么是設(shè)備驅(qū)動(dòng)?n 設(shè)備控制器的CSR用于啟動(dòng)和停止設(shè)備,初始化設(shè)備和診斷它的問(wèn)題n 管理這些硬件控制器的代碼不是放在每一個(gè)應(yīng)用程序里邊,而是放在Linux內(nèi)核中。這些處理或管理硬件控制器的軟件就叫做設(shè)備驅(qū)動(dòng)程序。n 一般來(lái)說(shuō),一個(gè)驅(qū)動(dòng)程序控制一種硬件設(shè)備;n Linux核心的設(shè)備驅(qū)動(dòng)程序是
3、Linux操作系統(tǒng)的一部分,它運(yùn)行于核心態(tài)。驅(qū)動(dòng)原理:驅(qū)動(dòng)架構(gòu)驅(qū)動(dòng)原理:驅(qū)動(dòng)架構(gòu)硬件設(shè)備驅(qū)動(dòng)塊設(shè)備字符設(shè)備緩沖區(qū)文件子系統(tǒng)進(jìn)程控制子系統(tǒng)進(jìn)程調(diào)度內(nèi)存管理調(diào)進(jìn)程間通訊系統(tǒng)調(diào)用接口硬件層內(nèi)核層內(nèi)核層用戶(hù)層庫(kù)函數(shù)用戶(hù)程序驅(qū)動(dòng)原理:內(nèi)核何時(shí)使用驅(qū)動(dòng)程序?驅(qū)動(dòng)原理:內(nèi)核何時(shí)使用驅(qū)動(dòng)程序?n Linux內(nèi)核使用“設(shè)備無(wú)關(guān)”的I/O子系統(tǒng)來(lái)為所有的設(shè)備服務(wù)。每個(gè)設(shè)備都提供標(biāo)準(zhǔn)接口給內(nèi)核,從而盡可能地隱藏了自己的特性。n 用戶(hù)程序使用一些基本的系統(tǒng)調(diào)用從設(shè)備讀取數(shù)據(jù)并且將它們存入緩沖。n 每當(dāng)一個(gè)系統(tǒng)調(diào)用被使用時(shí),內(nèi)核就轉(zhuǎn)到相應(yīng)的設(shè)備驅(qū)動(dòng)例程來(lái)操縱硬件。 驅(qū)動(dòng)原理:驅(qū)動(dòng)原理: Linux的的I/O子系統(tǒng)子系統(tǒng)
4、驅(qū)動(dòng)原理:驅(qū)動(dòng)原理:Linux設(shè)備與文件的關(guān)系設(shè)備與文件的關(guān)系n Linux將所有外部設(shè)備看成是一類(lèi)特殊文件,稱(chēng)之為“設(shè)備文件”,如果說(shuō)系統(tǒng)調(diào)用是Linux內(nèi)核和應(yīng)用程序之間的接口,那么設(shè)備驅(qū)動(dòng)程序則可以看成是Linux內(nèi)核與外部設(shè)備之間的接口。n 設(shè)備驅(qū)動(dòng)程序向應(yīng)用程序屏蔽了硬件在實(shí)現(xiàn)上的細(xì)節(jié),使得應(yīng)用程序可以像操作普通文件一樣來(lái)操作外部設(shè)備。驅(qū)動(dòng)原理:設(shè)備文件驅(qū)動(dòng)原理:設(shè)備文件nLinux抽象了對(duì)硬件的處理,使得所有的硬件設(shè)備都可以像普通文件一樣來(lái)看待:它們可以使用和操作文件相同的、標(biāo)準(zhǔn)的系統(tǒng)調(diào)用接口來(lái)完成打開(kāi)、關(guān)閉、讀寫(xiě)和I/O控制操作,而驅(qū)動(dòng)程序的主要任務(wù)也就是要實(shí)現(xiàn)這些系統(tǒng)調(diào)用函數(shù)。
5、nLinux系統(tǒng)中的所有硬件設(shè)備都使用一個(gè)特殊的設(shè)備文件來(lái)表示,例如,系統(tǒng)中的第一個(gè)IDE硬盤(pán)在文件系統(tǒng)中使用/dev/hda表示。nLinux通過(guò)分配設(shè)備號(hào)來(lái)標(biāo)識(shí)每個(gè)設(shè)備,每個(gè)設(shè)備文件對(duì)應(yīng)有兩個(gè)設(shè)備號(hào):一個(gè)是主設(shè)備號(hào),標(biāo)識(shí)該設(shè)備的種類(lèi),也標(biāo)識(shí)了該設(shè)備所使用的驅(qū)動(dòng)程序,有關(guān)主設(shè)備號(hào)分配見(jiàn)linux/include/linux/major.h 。例如軟驅(qū)主設(shè)備號(hào)是2,IDE硬盤(pán)的主設(shè)備號(hào)是3;另一個(gè)是次設(shè)備號(hào),標(biāo)識(shí)使用同一設(shè)備驅(qū)動(dòng)程序的不同硬件設(shè)備。例如,一臺(tái)PC有兩塊IDE硬盤(pán),它們的主設(shè)備號(hào)都是 3,但是第一個(gè)硬盤(pán)的次設(shè)備號(hào)為1,另一個(gè)次設(shè)備號(hào)為2。設(shè)備文件的主設(shè)備號(hào)必須與設(shè)備驅(qū)動(dòng)程序在登記
6、該設(shè)備時(shí)申請(qǐng)的主設(shè)備號(hào)一致,否則用戶(hù)進(jìn)程將無(wú)法訪(fǎng)問(wèn)到設(shè)備驅(qū)動(dòng)程序。驅(qū)動(dòng)原理:設(shè)備驅(qū)動(dòng)程序的主要功能驅(qū)動(dòng)原理:設(shè)備驅(qū)動(dòng)程序的主要功能n 對(duì)設(shè)備進(jìn)行初始化;n 使設(shè)備投入運(yùn)行和退出服務(wù);n 從設(shè)備接收數(shù)據(jù)并將它們送回內(nèi)核;n 將數(shù)據(jù)從內(nèi)核送到設(shè)備;n 檢測(cè)和處理設(shè)備出現(xiàn)的錯(cuò)誤。驅(qū)動(dòng)原理:字符設(shè)備和塊設(shè)備驅(qū)動(dòng)原理:字符設(shè)備和塊設(shè)備n 在Linux操作系統(tǒng)下有兩類(lèi)主要的設(shè)備文件:一類(lèi)是字符設(shè)備,另一類(lèi)則是塊設(shè)備。n 字符設(shè)備是以字節(jié)為單位逐個(gè)進(jìn)行I/O操作的設(shè)備,在對(duì)字符設(shè)備發(fā)出讀寫(xiě)請(qǐng)求時(shí),實(shí)際的硬件I/O緊接著就發(fā)生了,一般來(lái)說(shuō)字符設(shè)備中的緩存是可有可無(wú)的,而且也不支持隨機(jī)訪(fǎng)問(wèn)。如鼠標(biāo)、鍵盤(pán)、串口
7、n 塊設(shè)備則是利用一塊系統(tǒng)內(nèi)存作為緩沖區(qū),當(dāng)用戶(hù)進(jìn)程對(duì)設(shè)備進(jìn)行讀寫(xiě)請(qǐng)求時(shí),驅(qū)動(dòng)程序先查看緩沖區(qū)中的內(nèi)容,如果緩沖區(qū)中的數(shù)據(jù)能滿(mǎn)足用戶(hù)的要求就返回相應(yīng)的數(shù)據(jù),否則就調(diào)用相應(yīng)的請(qǐng)求函數(shù)來(lái)進(jìn)行實(shí)際的I/O操作。如硬盤(pán)、光驅(qū)等塊設(shè)備主要是針對(duì)磁盤(pán)等慢速設(shè)備設(shè)計(jì)的,其目的是避免耗費(fèi)過(guò)多的CPU時(shí)間來(lái)等待操作的完成。驅(qū)動(dòng)原理:設(shè)備文件與驅(qū)動(dòng)程序的關(guān)系驅(qū)動(dòng)原理:設(shè)備文件與驅(qū)動(dòng)程序的關(guān)系n 所有已經(jīng)注冊(cè)(即已經(jīng)加載了驅(qū)動(dòng)程序)的硬件設(shè)備的主設(shè)備號(hào)可以從/proc/devices文件中得到。n 使用mknod命令可以創(chuàng)建指定類(lèi)型的設(shè)備文件,同時(shí)為其分配相應(yīng)的主設(shè)備號(hào)和次設(shè)備號(hào)。mknod /dev/device
8、_name device_type major_number minor_number其中:device_name是此設(shè)備的文件device_type是此設(shè)備的類(lèi)型,c表示字符設(shè)備,b表示塊設(shè)備例如,建立一個(gè)主設(shè)備號(hào)為6,次設(shè)備號(hào)為0的字符設(shè)備文件/dev/lp0 :# mknod /dev/lp0 c 6 0 n 當(dāng)應(yīng)用程序?qū)δ硞€(gè)設(shè)備文件進(jìn)行系統(tǒng)調(diào)用時(shí),Linux內(nèi)核會(huì)根據(jù)該設(shè)備文件的設(shè)備類(lèi)型和主設(shè)備號(hào)調(diào)用相應(yīng)的驅(qū)動(dòng)程序,并從用戶(hù)態(tài)進(jìn)入到核心態(tài),再由驅(qū)動(dòng)程序判斷該設(shè)備的次設(shè)備號(hào),最終完成對(duì)相應(yīng)硬件的操作。驅(qū)動(dòng)機(jī)制:設(shè)備管理驅(qū)動(dòng)機(jī)制:設(shè)備管理n 1、設(shè)備管理:系統(tǒng)對(duì)已經(jīng)登記的字符設(shè)備的管理是由
9、chrdevs來(lái)管理的。n Linux對(duì)設(shè)備進(jìn)行訪(fǎng)問(wèn)時(shí),訪(fǎng)問(wèn)文件系統(tǒng)中相應(yīng)的設(shè)備文件,通過(guò)文件系統(tǒng)和文件的屬性描述塊,可以找到該文件系統(tǒng)或設(shè)備對(duì)應(yīng)的設(shè)備號(hào)。在實(shí)際訪(fǎng)問(wèn)列表時(shí),以chrdevsMAJORMINOR 形式訪(fǎng)問(wèn)。static struct char_device_struct struct char_device_struct *next;unsigned int major;unsigned int baseminor;int minorct;const char *name;struct *fops;struct cdev *cdev;/* will die */ *chrdev
10、sMAX_PROBE_HASH;驅(qū)動(dòng)機(jī)制:驅(qū)動(dòng)機(jī)制:I/O請(qǐng)求管理請(qǐng)求管理n 2、I/O請(qǐng)求管理:系統(tǒng)會(huì)把一部分系統(tǒng)內(nèi)存作為塊設(shè)備驅(qū)動(dòng)程序與文件系統(tǒng)接口之間的一層緩沖區(qū),每個(gè)緩沖區(qū)與某臺(tái)設(shè)備中的特定區(qū)域相聯(lián)系,文件系統(tǒng)首先試圖查找相應(yīng)的緩沖區(qū),如未找到才向該設(shè)備發(fā)出I/O讀寫(xiě)請(qǐng)求,由設(shè)備驅(qū)動(dòng)程序?qū)@些請(qǐng)求進(jìn)行處理。驅(qū)動(dòng)機(jī)制:中斷請(qǐng)求驅(qū)動(dòng)機(jī)制:中斷請(qǐng)求n 3、中斷請(qǐng)求:設(shè)備進(jìn)行實(shí)際的輸入/輸出時(shí),如果時(shí)間過(guò)長(zhǎng)而始終占用CPU,就會(huì)影響系統(tǒng)的效率,所以L(fǎng)inux采用中斷的機(jī)制。驅(qū)動(dòng)機(jī)制:中斷與輪詢(xún)驅(qū)動(dòng)機(jī)制:中斷與輪詢(xún)n設(shè)備被執(zhí)行某個(gè)命令時(shí),如“將讀取磁頭移動(dòng)到軟盤(pán)的第42扇區(qū)上”,設(shè)備驅(qū)動(dòng)可以從輪
11、詢(xún)方式和中斷方式中選擇一種以判斷設(shè)備是否已經(jīng)完成此命令。n輪詢(xún)方式意味著需要經(jīng)常讀取設(shè)備的狀態(tài),一直到設(shè)備狀態(tài)表明請(qǐng)求已經(jīng)完成為止。如果設(shè)備驅(qū)動(dòng)被連接進(jìn)入內(nèi)核,這時(shí)使用輪詢(xún)方式將會(huì)帶來(lái)災(zāi)難性后果:內(nèi)核將在此過(guò)程中無(wú)所事事,直到設(shè)備完成此請(qǐng)求。但是輪詢(xún)?cè)O(shè)備驅(qū)動(dòng)可以通過(guò)使用系統(tǒng)定時(shí)器,使核心周期性調(diào)用設(shè)備驅(qū)動(dòng)中的某個(gè)例程來(lái)檢查設(shè)備狀態(tài)。 定時(shí)器過(guò)程可以檢查命令狀態(tài)及Linux軟盤(pán)驅(qū)動(dòng)的工作情況。使用定時(shí)器是輪詢(xún)方式中最好的一種,但更有效的方法是使用中斷。 n基于中斷的設(shè)備驅(qū)動(dòng)會(huì)在它所控制的硬件設(shè)備需要服務(wù)時(shí)引發(fā)一個(gè)硬件中斷。如以太網(wǎng)設(shè)備驅(qū)動(dòng)從網(wǎng)絡(luò)上接收到一個(gè)以太數(shù)據(jù)報(bào)時(shí)都將引起中斷。Linux內(nèi)核
12、需要將來(lái)自硬件設(shè)備的中斷傳遞到相應(yīng)的設(shè)備驅(qū)動(dòng)。這個(gè)過(guò)程由設(shè)備驅(qū)動(dòng)向內(nèi)核注冊(cè)其使用的中斷來(lái)協(xié)助完成。此中斷處理例程的地址和中斷號(hào)都將被記錄下來(lái)。在/proc/interrupts文件中你可以看到設(shè)備驅(qū)動(dòng)所對(duì)應(yīng)的中斷號(hào)及類(lèi)型。驅(qū)動(dòng)機(jī)制:高速緩沖驅(qū)動(dòng)機(jī)制:高速緩沖n 4、高速緩沖區(qū):為了加速物理設(shè)備的訪(fǎng)問(wèn)速度,Linux將塊緩沖區(qū)放在cache內(nèi),塊緩沖區(qū)是由buff_head 連成的鏈表結(jié)構(gòu)。struct buff_head unsigned long b_blocknr 邏輯塊號(hào)unsigned long b_size 塊大小kdev_t b_dev 虛擬設(shè)備標(biāo)志符kdev_t b_rdev 實(shí)
13、際設(shè)備標(biāo)志符unsigned long b_state 緩沖區(qū)狀態(tài)標(biāo)志char * b_data 指向緩沖區(qū)的指針unsigned long b_rsector 實(shí)際設(shè)備上的塊號(hào).驅(qū)動(dòng)機(jī)制:驅(qū)動(dòng)機(jī)制: DMAn 有時(shí)設(shè)備與系統(tǒng)要進(jìn)行大批量的數(shù)據(jù)傳輸,采用中斷的方式會(huì)給CPU帶來(lái)很大的負(fù)荷,降低了系統(tǒng)的效率。n DMA操作是外設(shè)直接與內(nèi)存進(jìn)行數(shù)據(jù)傳輸,而無(wú)須CPU的干預(yù)。如硬盤(pán)數(shù)據(jù)傳輸、網(wǎng)卡數(shù)據(jù)傳輸?shù)?。n DMA控制器沒(méi)有任何虛擬內(nèi)存的概念,它只存取系統(tǒng)中的物理內(nèi)存,不能在進(jìn)程虛擬地址空間內(nèi)直接使用DMA。驅(qū)動(dòng)接口:設(shè)備驅(qū)動(dòng)程序與外界的接口驅(qū)動(dòng)接口:設(shè)備驅(qū)動(dòng)程序與外界的接口n 每種類(lèi)型的驅(qū)動(dòng)程序
14、,不管是字符設(shè)備還是塊設(shè)備都為內(nèi)核提供相同的調(diào)用接口,因此內(nèi)核能以相同的方式處理不同的設(shè)備。Linux為每種不同類(lèi)型的設(shè)備驅(qū)動(dòng)程序維護(hù)相應(yīng)的數(shù)據(jù)結(jié)構(gòu),以便定義統(tǒng)一的接口并實(shí)現(xiàn)驅(qū)動(dòng)程序的可裝載性和動(dòng)態(tài)性,n Linux設(shè)備驅(qū)動(dòng)程序與外界的接口分為3部分:驅(qū)動(dòng)程序與內(nèi)核的接口,這是通過(guò)數(shù)據(jù)結(jié)構(gòu)來(lái)完成的;驅(qū)動(dòng)程序與系統(tǒng)引導(dǎo)的接口,這部分利用驅(qū)動(dòng)程序?qū)υO(shè)備進(jìn)行初始化;設(shè)備驅(qū)動(dòng)程序與設(shè)備的接口,這部分描述了驅(qū)動(dòng)程序如何與設(shè)備進(jìn)行交互,這與具體設(shè)備密切相關(guān);它們之間的關(guān)系如下頁(yè)圖所示:驅(qū)動(dòng)接口:驅(qū)動(dòng)程序與外界的接口驅(qū)動(dòng)接口:驅(qū)動(dòng)程序與外界的接口 設(shè)備驅(qū)動(dòng)程序設(shè)備驅(qū)動(dòng)程序 操作系統(tǒng)內(nèi)核操作系統(tǒng)內(nèi)核 接口 數(shù)
15、據(jù)結(jié)構(gòu)數(shù)據(jù)結(jié)構(gòu) 實(shí)現(xiàn)實(shí)現(xiàn) 系統(tǒng)引導(dǎo)系統(tǒng)引導(dǎo) 接口 各設(shè)備各設(shè)備 初始化初始化 具體設(shè)備具體設(shè)備 接口 進(jìn)行交互進(jìn)行交互 驅(qū)動(dòng)程序與設(shè)備間驅(qū)動(dòng)程序與設(shè)備間 圖 設(shè)備驅(qū)動(dòng)程序與外界的接口 設(shè)備驅(qū)動(dòng)程序的特點(diǎn)設(shè)備驅(qū)動(dòng)程序的特點(diǎn)(1)內(nèi)核代碼:設(shè)備驅(qū)動(dòng)程序是內(nèi)核的一部分,如果驅(qū)動(dòng)程序出錯(cuò),則可能導(dǎo)致系統(tǒng)崩潰。 (2)內(nèi)核接口:設(shè)備驅(qū)動(dòng)程序必須為內(nèi)核或者其子系統(tǒng)提供一個(gè)標(biāo)準(zhǔn)接口。比如,一個(gè)終端驅(qū)動(dòng)程序必須為內(nèi)核提供一個(gè)文件I/O接口;一個(gè)SCSI設(shè)備驅(qū)動(dòng)程序應(yīng)該為SCSI子系統(tǒng)提供一個(gè)SCSI設(shè)備接口,同時(shí)SCSI子系統(tǒng)也必須為內(nèi)核提供文件的I/O接口及緩沖區(qū)。 (3)內(nèi)核機(jī)制和服務(wù):設(shè)備驅(qū)動(dòng)程序使用一
16、些標(biāo)準(zhǔn)的內(nèi)核服務(wù),如內(nèi)存分配等。 (4)可裝載:大多數(shù)的Linux操作系統(tǒng)設(shè)備驅(qū)動(dòng)程序都可以在需要時(shí)裝載進(jìn)內(nèi)核,在不需要時(shí)從內(nèi)核中卸載。 (5)可設(shè)置:Linux 操作系統(tǒng)設(shè)備驅(qū)動(dòng)程序可以集成為內(nèi)核的一部分,并可以根據(jù)需要把其中的某一部分集成到內(nèi)核中,這只需要在系統(tǒng)編譯時(shí)進(jìn)行相應(yīng)的設(shè)置即可。 (6)動(dòng)態(tài)性:在系統(tǒng)啟動(dòng)且各個(gè)設(shè)備驅(qū)動(dòng)程序初始化后,驅(qū)動(dòng)程序?qū)⒕S護(hù)其控制的設(shè)備。如果該設(shè)備驅(qū)動(dòng)程序控制的設(shè)備不存在也不影響系統(tǒng)的運(yùn)行,那么此時(shí)的設(shè)備驅(qū)動(dòng)程序只是多占用了一點(diǎn)系統(tǒng)內(nèi)存罷了思考思考n 設(shè)備驅(qū)動(dòng)與文件的關(guān)系?提綱提綱n 設(shè)備驅(qū)動(dòng)概述n 如何編寫(xiě)內(nèi)核模塊n 如何編寫(xiě)設(shè)備驅(qū)動(dòng)n 字符設(shè)備驅(qū)動(dòng)實(shí)例內(nèi)核
17、模塊內(nèi)核模塊n在開(kāi)始編寫(xiě)設(shè)備驅(qū)動(dòng)之前,先需要了解內(nèi)核模塊的概念。Linux內(nèi)核是一個(gè)整體的結(jié)構(gòu),因此向內(nèi)核添加任何東西或者刪除某些功能,都十分困難。為了解決這個(gè)問(wèn)題,Linux引入了內(nèi)核模塊機(jī)制,從而可以動(dòng)態(tài)地在內(nèi)核中添加或者刪除模塊nLinux內(nèi)核中采用可加載的模塊化設(shè)計(jì) (LKMs, Loadable Kernel Modules) ,一般情況下編譯的 Linux 內(nèi)核是支持可插入式模塊的,也就是將最基本的核心代碼編譯在內(nèi)核中,其他的代碼可以選擇在內(nèi)核中,或者編譯為內(nèi)核的模塊文件。 n常見(jiàn)的驅(qū)動(dòng)程序也是作為內(nèi)核模塊動(dòng)態(tài)加載的,比如聲卡驅(qū)動(dòng)和網(wǎng)卡驅(qū)動(dòng)等,而 Linux最基礎(chǔ)的驅(qū)動(dòng),如CPU、
18、PCI總線(xiàn)、TCP/IP協(xié)議、APM(高級(jí)電源管理)、VFS等驅(qū)動(dòng)程序則直接編譯在內(nèi)核文件中。有時(shí)也把內(nèi)核模塊叫做驅(qū)動(dòng)程序,只不過(guò)驅(qū)動(dòng)的內(nèi)容不一定是硬件罷了,比如 ext3 文件系統(tǒng)的驅(qū)動(dòng)。因此,加載驅(qū)動(dòng)時(shí)就是加載內(nèi)核模塊。n模塊不被編譯在內(nèi)核中,因而控制了內(nèi)核的大小。然而模塊一旦被插入內(nèi)核,它就和內(nèi)核其他部分一樣。這樣一來(lái)就會(huì)增加一部分系統(tǒng)開(kāi)銷(xiāo)。同時(shí),如果模塊出現(xiàn)問(wèn)題,也許會(huì)帶來(lái)系統(tǒng)崩潰。所以在進(jìn)行模塊開(kāi)發(fā)時(shí),要特別注意與應(yīng)用程序開(kāi)發(fā)的區(qū)別。n 常用的模塊命令如下:lsmod顯示當(dāng)前系統(tǒng)已經(jīng)加載的模塊rmmod是用于將當(dāng)前模塊卸載。insmod 和 modprobe 是用于加載當(dāng)前模塊但 i
19、nsmod 不會(huì)自動(dòng)解決依存關(guān)系而modprobe則可以根據(jù)模塊間依存關(guān)系以及/etc/modules.conf文件中的內(nèi)容自動(dòng)插入模塊。n mknod是用于創(chuàng)建設(shè)備節(jié)點(diǎn)。如果需要加載的模塊是一個(gè)設(shè)備驅(qū)動(dòng)模塊,它占用一個(gè)主設(shè)備號(hào),那么在加載此模塊前,必須先為它在文件系統(tǒng)中建立好相應(yīng)的設(shè)備節(jié)點(diǎn) 。n 例如:為設(shè)備驅(qū)動(dòng)模塊test.ko建立字符設(shè)備節(jié)點(diǎn)test,其主設(shè)備號(hào)為254,次設(shè)備為0n mknod /dev/test c 254 0舉例:簡(jiǎn)單的內(nèi)核模塊舉例:簡(jiǎn)單的內(nèi)核模塊下面舉一個(gè)簡(jiǎn)單的內(nèi)核模塊例子,以此引出內(nèi)核的機(jī)制和框架:/* hello.c */#include #include #
20、include static int hello_init(void)printk(KERN_ALERT Hello, worldn);return 0;static void hello_exit(void)printk(KERN_ALERT Goodbye, cruel worldn);module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE(GPL);編譯模塊編譯模塊n 下面是一個(gè)典型的2.6內(nèi)核下模塊的Makefile#Make hello.c file#KDIR:=/lib/modules/$(shell uname
21、 -r)/buildobj-m:=hello.odefault: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modulesclean: $(RM) .*.cmd *.mod.c *.o *.ko -r .tmp*n 執(zhí)行make即可生成hello.ko測(cè)試模塊測(cè)試模塊1、以root用戶(hù)登錄,運(yùn)行tail -f /var/log/messages2、在另外一個(gè)終端以root用戶(hù)登錄,裝載模塊insmod ./hello.ko3、這時(shí)會(huì)在/var/log/messages看到如下信息:Mar 25 16:50:51 wpon kernel: Hello, world4、卸
22、載模塊Now remove the module:rmmod hello5、這時(shí)會(huì)在/var/log/messages看到如下信息:Mar 25 16:51:08 wpon kernel: Goodbye, cruel world模塊機(jī)制模塊機(jī)制n從上面的例子可以看出,加載模塊的方式與以往的應(yīng)用程序開(kāi)發(fā)有很大的不同。以往在開(kāi)發(fā)應(yīng)用程序時(shí)都有一個(gè) main函數(shù)作程序的入口點(diǎn),而在模塊開(kāi)發(fā)時(shí)卻沒(méi)有 main 函數(shù),模塊在調(diào)用 insmod命令時(shí)被加載,此時(shí)的入口點(diǎn)是module_init函數(shù)。同樣,模塊在調(diào)用 rmmod函數(shù)時(shí)被卸載,此時(shí)的出口點(diǎn)是module_exit函數(shù)。模塊初始化時(shí)執(zhí)行mod
23、ule_init入口點(diǎn)模塊不再使用時(shí)(手工或關(guān)機(jī)時(shí))執(zhí)行module_exit出口點(diǎn)編寫(xiě)模塊的規(guī)則編寫(xiě)模塊的規(guī)則n 不能訪(fǎng)問(wèn)C庫(kù)如 printf(), strcat(),只能使用內(nèi)核提供的頭文件n 內(nèi)核有自己的C功能函數(shù),如類(lèi)似于printf()的printk()n 只能使用內(nèi)核提供的頭文件n 不要使用浮點(diǎn)數(shù)n 聲明變量為static的,防止命名空間污染模塊調(diào)試技術(shù)模塊調(diào)試技術(shù)n 內(nèi)核對(duì)調(diào)試的支持:配置內(nèi)核時(shí)make menuconfig注意選擇debug,編程時(shí)CONFIG_DEBUG_INFO等宏的引用n printk及信息顯示級(jí)別n /proc系統(tǒng)提供的信息printkn就如同在編寫(xiě)用戶(hù)
24、空間的應(yīng)用程序,打印信息有時(shí)是很好的調(diào)試手段,也是在代碼中很常用的組成部分。但是與用戶(hù)空間不同,在內(nèi)核空間要用函數(shù) printk 而不能用平常的函數(shù)printf。printk和 printf很類(lèi)似,都可以按照一定的格式打印消息,所不同的是,printk還可以定義打印消息的優(yōu)先級(jí)。這些不同優(yōu)先級(jí)的信息可以輸出到控制臺(tái)上、/var/log/messages里。其中,對(duì)輸出給控制臺(tái)的信息有一個(gè)特定的優(yōu)先級(jí)console_loglevel。若優(yōu)先級(jí)小于這個(gè)整數(shù)值時(shí),則消息才能顯示到控制臺(tái)上,否則,消息會(huì)顯示在/var/log/messages 里。若不加任何優(yōu)先級(jí)選項(xiàng),則消息默認(rèn)輸出到/var/log
25、/messages文件中。 printkn include/linux/kernel.h下對(duì)不同日志級(jí)別的定義#define KERN_EMERG /* system is unusable */#define KERN_ALERT /* action must be taken immediately */#define KERN_CRIT /* critical conditions */#define KERN_ERR /* error conditions */#define KERN_WARNING /* warning conditions */#define KERN_NOTIC
26、E /* normal but significant condition */#define KERN_INFO /* informational */#define KERN_DEBUG /* debug-level messages */n 優(yōu)先級(jí)console_loglevel被指定為18之間的整數(shù)值。如果設(shè)定為1,則只有級(jí)別為0的信息才能到達(dá)控制臺(tái)。如果設(shè)定為8,則包括調(diào)試信息在內(nèi)的所有消息都顯示出來(lái)/procn /proc 文件系統(tǒng)是一個(gè)偽文件系統(tǒng),它是一種內(nèi)核和內(nèi)核模塊用來(lái)向進(jìn)程發(fā)送信息的機(jī)制。這個(gè)偽文件系統(tǒng)讓用戶(hù)可以和內(nèi)核內(nèi)部數(shù)據(jù)結(jié)構(gòu)進(jìn)行交互,獲取有關(guān)進(jìn)程的有用信息,在運(yùn)行時(shí)通
27、過(guò)改變內(nèi)核參數(shù)改變?cè)O(shè)置。與其他文件系統(tǒng)不同,/proc存在于內(nèi)存之中而不是硬盤(pán)上,在加載模塊成功后,可以使用查看/proc/device文件獲得相關(guān)設(shè)備的主設(shè)備號(hào)。 思考思考n 內(nèi)核何時(shí)調(diào)用模塊?lsmod和/proc/modules當(dāng)內(nèi)核需要的某功能不存在時(shí)通過(guò)運(yùn)行modprobe調(diào)入相應(yīng)模塊,modprobe運(yùn)行前檢查依賴(lài)關(guān)系/lib/modules/$(shell uname -r)/modules.depinsmodrmmodn 模塊是如何工作的?通過(guò)module_init告訴內(nèi)核本模塊提供的操作函數(shù)當(dāng)內(nèi)核需要操作模塊時(shí)則調(diào)用模塊提供的函數(shù)模塊不再使用時(shí)執(zhí)行module_exit,手工
28、或關(guān)機(jī)時(shí)提綱提綱n 設(shè)備驅(qū)動(dòng)概述n 如何編寫(xiě)內(nèi)核模塊n 如何編寫(xiě)設(shè)備驅(qū)動(dòng)n 字符設(shè)備驅(qū)動(dòng)實(shí)例設(shè)備驅(qū)動(dòng)編寫(xiě)流程設(shè)備驅(qū)動(dòng)編寫(xiě)流程 n在上一節(jié)中已經(jīng)提到,模塊在調(diào)用 insmod命令時(shí)被加載,此時(shí)的入口點(diǎn)是module_init函數(shù),通常在該函數(shù)中完成設(shè)備的注冊(cè)。同樣,模塊在調(diào)用 rmmod函數(shù)時(shí)被卸載,此時(shí)的入口點(diǎn)是module_exit函數(shù),在該函數(shù)中完成設(shè)備的卸載。在設(shè)備完成注冊(cè)加載之后,用戶(hù)的應(yīng)用程序就可以對(duì)該設(shè)備進(jìn)行一定的操作,如read、write等,而驅(qū)動(dòng)程序就是用于實(shí)現(xiàn)這些操作,在用戶(hù)應(yīng)用程序調(diào)用相應(yīng)入口函數(shù)時(shí)執(zhí)行相關(guān)的操作。設(shè)備驅(qū)動(dòng)程序流程圖如下所示:驅(qū)動(dòng)接口:向內(nèi)核提供的設(shè)備操作
29、接口驅(qū)動(dòng)接口:向內(nèi)核提供的設(shè)備操作接口nLinux中的I/O子系統(tǒng)向內(nèi)核中的其他部分提供了一個(gè)統(tǒng)一的標(biāo)準(zhǔn)設(shè)備接口,這是通過(guò)include/linux/fs.h中的數(shù)據(jù)結(jié)構(gòu)來(lái)完成的:struct loff_t (*llseek) (struct file *, loff_t, int); ssize_t (*read) (struct file *, char *, size_t, loff_t *); ssize_t (*write) (struct file *, const char *, size_t, loff_t *); unsigned int (*poll) (struct fi
30、le *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); ; n這個(gè)結(jié)構(gòu)的每一個(gè)成員的名字都對(duì)應(yīng)著一個(gè)系統(tǒng)調(diào)用.用戶(hù)進(jìn)程利用系統(tǒng)調(diào)用在對(duì)設(shè)備文件
31、進(jìn)行如read/write操作時(shí),系統(tǒng)調(diào)用通過(guò)設(shè)備文件的主設(shè)備號(hào)找到相應(yīng)的設(shè)備驅(qū)動(dòng)程序,然后讀取這個(gè)數(shù)據(jù)結(jié)構(gòu)相應(yīng)的函數(shù)指針,接著把控制權(quán)交給該函數(shù).例如,當(dāng)應(yīng)用程序?qū)υO(shè)備文件執(zhí)行讀操作時(shí),內(nèi)核將調(diào)用結(jié)構(gòu)中的read函數(shù)。驅(qū)動(dòng)結(jié)構(gòu):驅(qū)動(dòng)程序的結(jié)構(gòu)驅(qū)動(dòng)結(jié)構(gòu):驅(qū)動(dòng)程序的結(jié)構(gòu)n Linux的設(shè)備驅(qū)動(dòng)程序大致可以分為如下幾個(gè)部分: 驅(qū)動(dòng)程序的注冊(cè)與注銷(xiāo) 設(shè)備的打開(kāi)與釋放 設(shè)備的讀寫(xiě)操作 設(shè)備的控制操作 設(shè)備的中斷和輪詢(xún)處理驅(qū)動(dòng)結(jié)構(gòu):驅(qū)動(dòng)程序的注冊(cè)與注銷(xiāo)驅(qū)動(dòng)結(jié)構(gòu):驅(qū)動(dòng)程序的注冊(cè)與注銷(xiāo) n舊方式:向系統(tǒng)增加一個(gè)驅(qū)動(dòng)程序意味著要賦予它一個(gè)主設(shè)備號(hào),這可以通過(guò)在驅(qū)動(dòng)程序的初始化過(guò)程中調(diào)用register_chr
32、dev( )或者register_blkdev( )來(lái)完成。而在關(guān)閉字符設(shè)備或者塊設(shè)備時(shí),則需要通過(guò)調(diào)用unregister_chrdev( )或unregister_blkdev( )從內(nèi)核中注銷(xiāo)設(shè)備,同時(shí)釋放占用的主設(shè)備號(hào)。 n新方式:#include n注冊(cè):void cdev_init(struct cdev *dev,struct *fops);int cdev_add(struct cdev *dev,dev_t num,unsigned int count);n注銷(xiāo):void cdev_del(struct cdev *dev);驅(qū)動(dòng)結(jié)構(gòu):設(shè)備的打開(kāi)與釋放驅(qū)動(dòng)結(jié)構(gòu):設(shè)備的打開(kāi)與釋
33、放 n 打開(kāi)設(shè)備是通過(guò)調(diào)用結(jié)構(gòu)中的函數(shù)open( )來(lái)完成的,它是驅(qū)動(dòng)程序用來(lái)為今后的操作完成初始化準(zhǔn)備工作的。在大部分驅(qū)動(dòng)程序中,open( )通常需要完成下列工作:1.檢查設(shè)備相關(guān)錯(cuò)誤,如設(shè)備尚未準(zhǔn)備好等。2.如果是第一次打開(kāi),則初始化硬件設(shè)備。3.識(shí)別次設(shè)備號(hào),如果有必要?jiǎng)t更新讀寫(xiě)操作的當(dāng)前位置指針f_ops。4.分配和填寫(xiě)要放在file-private_data里的數(shù)據(jù)結(jié)構(gòu)。n 釋放設(shè)備是通過(guò)調(diào)用結(jié)構(gòu)中的函數(shù)release( )來(lái)完成的,這個(gè)設(shè)備方法有時(shí)也被稱(chēng)為close( ),它的作用正好與open( )相反,通常要完成下列工作: 1.釋放在file-private_data中分配的
34、內(nèi)存。2.關(guān)閉設(shè)備。驅(qū)動(dòng)結(jié)構(gòu):設(shè)備的讀寫(xiě)操作驅(qū)動(dòng)結(jié)構(gòu):設(shè)備的讀寫(xiě)操作 n 字符設(shè)備的讀寫(xiě)操作相對(duì)比較簡(jiǎn)單,直接使用函數(shù)read( )和write( )。n 如果是塊設(shè)備,則需要調(diào)用函數(shù)block_read( )和block_write( )來(lái)進(jìn)行數(shù)據(jù)讀寫(xiě),這兩個(gè)函數(shù)將向設(shè)備請(qǐng)求表中增加讀寫(xiě)請(qǐng)求,以便Linux內(nèi)核可以對(duì)請(qǐng)求順序進(jìn)行優(yōu)化。由于是對(duì)內(nèi)存緩沖區(qū)而不是直接對(duì)設(shè)備進(jìn)行操作的,因此能很大程度上加快讀寫(xiě)速度。如果內(nèi)存緩沖區(qū)中沒(méi)有所要讀入的數(shù)據(jù),或者需要執(zhí)行寫(xiě)操作將數(shù)據(jù)寫(xiě)入設(shè)備,那么就要執(zhí)行真正的數(shù)據(jù)傳輸,這是通過(guò)調(diào)用數(shù)據(jù)結(jié)構(gòu)blk_dev_struct中的函數(shù)request_fn( )來(lái)完成
35、的。 nssize_t read(struct file *filp,char _user *buff,size_t count, loff_t *offp);nssize_t write(struct file *filp,const char _user *buff,size_t count, loff_t *offp);驅(qū)動(dòng)結(jié)構(gòu):設(shè)備的讀寫(xiě)操作注意驅(qū)動(dòng)結(jié)構(gòu):設(shè)備的讀寫(xiě)操作注意n在read和write參數(shù)里的_user表明,這個(gè)緩沖是用戶(hù)空間的指針,因此它不能直接被內(nèi)核代碼復(fù)引用。原因如下:在內(nèi)核執(zhí)行的過(guò)程中,用戶(hù)空間的指針也許還是無(wú)效的(如:還沒(méi)有給這個(gè)地址映射,或者它指向別的空間,或者
36、是隨機(jī)的數(shù)據(jù));即使這個(gè)指針指的就是內(nèi)核空間的同一空間,但是用戶(hù)空間是基于頁(yè)的,而在這里討論的這個(gè)內(nèi)存空間在系統(tǒng)調(diào)用執(zhí)行的時(shí)候也許還不在RAM中。直接引用用戶(hù)空間的內(nèi)存,會(huì)產(chǎn)生缺頁(yè)錯(cuò)誤;用戶(hù)空間提供的這個(gè)指針也許會(huì)有錯(cuò)誤,也許是有惡意的。這樣如果驅(qū)動(dòng)程序盲目地引用用戶(hù)空間的指針,就會(huì)給應(yīng)用程序提供一個(gè)訪(fǎng)問(wèn)內(nèi)核空間的后門(mén)。n因此,驅(qū)動(dòng)程序需要使用內(nèi)核提供的特別函數(shù)控制這些對(duì)指針的訪(fǎng)問(wèn),以完成任務(wù),這可以通過(guò)提供的內(nèi)核函數(shù),在這里就要使用 copy_to_user 或copy_from_user 函數(shù),它們就是用來(lái)實(shí)現(xiàn)用戶(hù)空間和內(nèi)核空間的數(shù)據(jù)交換的驅(qū)動(dòng)結(jié)構(gòu):設(shè)備的控制操作驅(qū)動(dòng)結(jié)構(gòu):設(shè)備的控制操作
37、n 除了讀寫(xiě)操作外,應(yīng)用程序有時(shí)還需要對(duì)設(shè)備進(jìn)行控制,這可以通過(guò)設(shè)備驅(qū)動(dòng)程序中的函數(shù)ioctl( )來(lái)完成。n ioctl是設(shè)備驅(qū)動(dòng)程序中對(duì)設(shè)備的I/O通道進(jìn)行管理的函數(shù)。所謂對(duì)I/O通道進(jìn)行管理,就是對(duì)設(shè)備的一些特性進(jìn)行控制,例如串口的傳輸波特率、馬達(dá)的轉(zhuǎn)速等等。n ioctl( )的用法與具體設(shè)備密切關(guān)聯(lián),因此需要根據(jù)設(shè)備的實(shí)際情況進(jìn)行具體分析。n 設(shè)備驅(qū)動(dòng)程序的ioctl函數(shù):int (*ioctl) (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); 命令號(hào):類(lèi)型、序號(hào)、方向、大小
38、。include/asm/ioctl.hDocumentation/ioctl-number.txt驅(qū)動(dòng)結(jié)構(gòu):用戶(hù)對(duì)設(shè)備的控制操作驅(qū)動(dòng)結(jié)構(gòu):用戶(hù)對(duì)設(shè)備的控制操作n 在用戶(hù)空間內(nèi)調(diào)用的ioctl函數(shù):int ioctl(int fd, unsigned long cmd, .);n fd就是用戶(hù)程序打開(kāi)設(shè)備時(shí)使用open函數(shù)返回的文件標(biāo)識(shí)符,cmd就是用戶(hù)程序?qū)υO(shè)備的控制命令,后面的省略號(hào),那是一些補(bǔ)充參數(shù),一般最多一個(gè),有或沒(méi)有是和cmd的意義相關(guān)的。驅(qū)動(dòng)模塊:驅(qū)動(dòng)模塊說(shuō)明驅(qū)動(dòng)模塊:驅(qū)動(dòng)模塊說(shuō)明n Linux下的設(shè)備驅(qū)動(dòng)程序可以按照兩種方式進(jìn)行編譯,一種是直接靜態(tài)編譯成內(nèi)核的一部分,另一種則是
39、編譯成可以動(dòng)態(tài)加載的模塊。如果編譯進(jìn)內(nèi)核的話(huà),會(huì)增加內(nèi)核的大小,還要改動(dòng)內(nèi)核的源文件,而且不能動(dòng)態(tài)地卸載,不利于調(diào)試,所以推薦使用模塊方式。n 從本質(zhì)上來(lái)講,模塊也是內(nèi)核的一部分,它不同于普通的應(yīng)用程序,不能調(diào)用位于用戶(hù)態(tài)下的C或者C+庫(kù)函數(shù),而只能調(diào)用Linux內(nèi)核提供的函數(shù),在/proc/kallsyms中可以查看到內(nèi)核提供的所有函數(shù)。驅(qū)動(dòng)模塊:模塊化驅(qū)動(dòng)的編寫(xiě)說(shuō)明驅(qū)動(dòng)模塊:模塊化驅(qū)動(dòng)的編寫(xiě)說(shuō)明n 在以模塊方式編寫(xiě)驅(qū)動(dòng)程序時(shí),要實(shí)現(xiàn)兩個(gè)必不可少的函數(shù)module_init ( )和module_exit( ),而且至少要包含兩個(gè)頭文件(、 )。n 編譯生成的模塊(一般為.ko文件)可以使用
40、命令insmod載入Linux內(nèi)核,從而成為內(nèi)核的一個(gè)組成部分,此時(shí)內(nèi)核會(huì)調(diào)用模塊中的函數(shù)module_init ( )。當(dāng)不再需要該模塊時(shí),可以使用rmmod命令進(jìn)行卸載,此時(shí)內(nèi)核會(huì)調(diào)用模塊中的函數(shù)module_exit( )。任何時(shí)候都可以使用命令lsmod查看目前已經(jīng)加載的模塊以及正在使用該模塊的用戶(hù)數(shù)。 思考思考n register_chrdev ()與misc_register ()有何聯(lián)系與區(qū)別?misc_register ()用來(lái)注冊(cè)其他類(lèi)型設(shè)備的,它的主設(shè)備是10調(diào)用register_chrdev(),設(shè)備名和函數(shù)指針通過(guò)miscdevice結(jié)構(gòu)獲得,同時(shí)結(jié)構(gòu)體還保存設(shè)備的次設(shè)
41、備號(hào)提綱提綱n 設(shè)備驅(qū)動(dòng)概述n 如何編寫(xiě)內(nèi)核模塊n 如何編寫(xiě)設(shè)備驅(qū)動(dòng)n 字符設(shè)備驅(qū)動(dòng)實(shí)例基于字符設(shè)備的基于字符設(shè)備的LinuxLinux驅(qū)動(dòng)程序設(shè)計(jì)實(shí)例驅(qū)動(dòng)程序設(shè)計(jì)實(shí)例n 實(shí)驗(yàn)?zāi)康恼莆誏inux設(shè)備模塊驅(qū)動(dòng)開(kāi)發(fā)的方法掌握Linux字符設(shè)備驅(qū)動(dòng)的開(kāi)發(fā)n 實(shí)驗(yàn)內(nèi)容調(diào)試一個(gè)簡(jiǎn)單字符設(shè)備驅(qū)動(dòng)程序用提供的應(yīng)用程序測(cè)試驅(qū)動(dòng)程序n 下面舉一個(gè)虛擬的字符驅(qū)動(dòng)程序舉例基于內(nèi)存拷貝的簡(jiǎn)單字符驅(qū)動(dòng)程序設(shè)計(jì)。實(shí)驗(yàn)步驟實(shí)驗(yàn)步驟n編寫(xiě)字符驅(qū)動(dòng)程序(test.c); 確定設(shè)備名稱(chēng)與主設(shè)備號(hào)根據(jù)需要編寫(xiě)設(shè)備文件對(duì)內(nèi)核上層的接口,比如open, release, read, write, ioctl等(test.c);n寫(xiě)Ma
42、kefile,編譯生成模塊目標(biāo)文件(test.ko)n用insmod將動(dòng)態(tài)加載驅(qū)動(dòng)模塊n在目錄/dev下用mknod命令建立相應(yīng)的設(shè)備文件n在用戶(hù)態(tài)下編寫(xiě)應(yīng)用程序測(cè)試,使用該設(shè)備驅(qū)動(dòng) (mytest.c)n編譯運(yùn)行測(cè)試用例驗(yàn)證驅(qū)動(dòng)正確性字符驅(qū)動(dòng)程序代碼字符驅(qū)動(dòng)程序代碼test.c#include #include #include #include #include #include #include #include #include #include #include MODULE_LICENSE(Dual BSD/GPL);#define DEVICE_NAME teststatic u
43、nsigned int test_major = 0;字符驅(qū)動(dòng)程序代碼字符驅(qū)動(dòng)程序代碼test.cstatic int read_test(struct file * *buf,size_t count,loff_t *ppos) int left; if (access_ok(VERIFY_WRITE,buf,count) = -EFAULT ) return -EFAULT; for(left = count ; left 0 ; left-) _put_user(1,buf); buf+; return count;static int write_test(struct file * *buf,size_t count,loff_t *ppos) return count;將獲得的數(shù)據(jù)送到用戶(hù)空間中檢查用戶(hù)空間中的內(nèi)存塊是否可用字符驅(qū)動(dòng)程序代碼字符驅(qū)動(dòng)程序代碼test.cstatic int open_test(struct inode * inode , struct file
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 學(xué)校食品安全管理制度
- 生活垃圾填埋場(chǎng)滲濾液處理雨污分流方案
- 門(mén)診隨訪(fǎng)制度
- 2023年齊齊哈爾市訥河市大學(xué)生鄉(xiāng)村醫(yī)生專(zhuān)項(xiàng)計(jì)劃招聘筆試真題
- 2023年崇州市教育局招聘教師考試真題
- 成套低壓配電箱(柜)安裝施工方案
- 小學(xué)勞動(dòng)節(jié)活動(dòng)策劃方案
- 2024設(shè)立中外計(jì)算機(jī)(硬件)產(chǎn)品合資經(jīng)營(yíng)企業(yè)合同
- 工程竣工決算管理制度
- 戶(hù)外傳媒LED顯示屏工程方案
- 中國(guó)新聞事業(yè)史 知到智慧樹(shù)網(wǎng)課答案
- 新質(zhì)生產(chǎn)力-講解課件
- 形勢(shì)與政策(論當(dāng)前國(guó)際形勢(shì)和中國(guó)外交)
- 第六章常微分方程
- 組織行為與領(lǐng)導(dǎo)力智慧樹(shù)知到期末考試答案2024年
- 《研學(xué)旅行課程設(shè)計(jì)》課件-體驗(yàn)式學(xué)習(xí)課程內(nèi)容設(shè)計(jì)
- 藝術(shù)中國(guó)智慧樹(shù)知到期末考試答案2024年
- 30道計(jì)量員崗位常見(jiàn)面試問(wèn)題含HR問(wèn)題考察點(diǎn)及參考回答
- 高等職業(yè)教育專(zhuān)科英語(yǔ)課程標(biāo)準(zhǔn)(2021版)
- 分布式光伏發(fā)電項(xiàng)目EPC總包合同
- 廣東省深圳市福田區(qū)2023-2024學(xué)年六年級(jí)上學(xué)期11月期中科學(xué)試題
評(píng)論
0/150
提交評(píng)論