linux設(shè)備驅(qū)動程序開發(fā)課件_第1頁
linux設(shè)備驅(qū)動程序開發(fā)課件_第2頁
linux設(shè)備驅(qū)動程序開發(fā)課件_第3頁
linux設(shè)備驅(qū)動程序開發(fā)課件_第4頁
linux設(shè)備驅(qū)動程序開發(fā)課件_第5頁
已閱讀5頁,還剩77頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第七章linux設(shè)備驅(qū)動程序開發(fā)第一頁,共八十二頁。7.1設(shè)備驅(qū)動概述設(shè)備驅(qū)動可以理解為操作系統(tǒng)的一部分,對于一個特定的硬件設(shè)備來說,其對應(yīng)的設(shè)備驅(qū)動程序是不同的。比如網(wǎng)卡、聲卡、鍵盤、鼠標(biāo)、顯卡等。對于操作系統(tǒng)來說,掛接的設(shè)備越多,所需要的設(shè)備驅(qū)動程序也越多。操作系統(tǒng)本身并沒有對種類繁多的硬件設(shè)備提供持久不變的“設(shè)備驅(qū)動”,也就是說操作系統(tǒng)在沒有設(shè)備驅(qū)動程序支持下是無法正常支配硬件行為的。這個時候就需要獨(dú)立開發(fā)一套適合自己產(chǎn)品的設(shè)備驅(qū)動。正是操作系統(tǒng)留下了擴(kuò)展設(shè)備驅(qū)動的接口,才有了現(xiàn)在支持各種應(yīng)用場合的硬件設(shè)備的蓬勃發(fā)展。對于嵌入式開發(fā),更沒有通用的驅(qū)動程序可以便用。因此,驅(qū)動程序開發(fā)是整個嵌入式系統(tǒng)設(shè)計(jì)過程中必不可少的一部分。第二頁,共八十二頁。7.1設(shè)備驅(qū)動概述7.1.1設(shè)備驅(qū)動程序功能設(shè)備驅(qū)動程序是Linux內(nèi)核的重要組成部分。像操作系統(tǒng)的其他部分一樣,驅(qū)動程序在一個高優(yōu)先級的環(huán)境下工作,如果發(fā)生錯誤則可能會引發(fā)嚴(yán)重的問題。設(shè)備驅(qū)動程序控制了操作系統(tǒng)和硬件設(shè)備之間的交互,完成以下功能:對設(shè)備初始化和釋放;對設(shè)備進(jìn)行管理,包括實(shí)時參數(shù)設(shè)置,以及提供對設(shè)備的操作接口;

讀取應(yīng)用程序傳送給設(shè)備文件的數(shù)據(jù)或者回送應(yīng)用程序請求的數(shù)據(jù);檢測和處理設(shè)備出現(xiàn)的錯誤。第三頁,共八十二頁。應(yīng)用程序硬件層驅(qū)動程序文件系統(tǒng)整個設(shè)備管理子系統(tǒng)的結(jié)構(gòu)如圖7.1所示。第四頁,共八十二頁。7.1設(shè)備驅(qū)動概述2.Linux設(shè)備驅(qū)動程序接口系統(tǒng)調(diào)用是操作系統(tǒng)內(nèi)核與應(yīng)用程序之間的接口,驅(qū)動程序則是操作系統(tǒng)內(nèi)核與機(jī)器硬件的接口。設(shè)備驅(qū)動程序能夠直接訪問硬件的代碼,必須為應(yīng)用程序提供系統(tǒng)調(diào)用。以便應(yīng)用程序能訪問設(shè)備。在LINUX中,主要有三種設(shè)備即:字符設(shè)備.塊設(shè)備和網(wǎng)絡(luò)設(shè)備,與此相關(guān)主要有三類設(shè)備驅(qū)動程序,字符設(shè)備驅(qū)動程序,塊設(shè)備驅(qū)動程序和網(wǎng)絡(luò)設(shè)備驅(qū)動程序.他們的系統(tǒng)調(diào)用是一致的,采用統(tǒng)一的接口(在數(shù)據(jù)結(jié)構(gòu)

中)。應(yīng)用程序使用設(shè)備就像使用讀寫普通的文件一樣方便,使用相同的open(),close(),read(),write()等,真正做到了與設(shè)備無關(guān)。第五頁,共八十二頁。7.1.2設(shè)備類型

Linux中的設(shè)備可以分為三類:字符設(shè)備塊設(shè)備網(wǎng)絡(luò)設(shè)備一個運(yùn)行的linux系統(tǒng),當(dāng)前使用的設(shè)備可以通過文件/proc/devices查看。

第六頁,共八十二頁。驅(qū)動程序中涉及的幾個概念模塊的概念Linux可以以模塊的形式加載設(shè)備類型,通常來說一個模塊對應(yīng)實(shí)現(xiàn)一個設(shè)備驅(qū)動,因此是可以分類的。一般一個設(shè)備驅(qū)動對應(yīng)一類設(shè)備的模塊方式,這樣便于多個設(shè)備的協(xié)調(diào)工作也利于應(yīng)用程序的開發(fā)和擴(kuò)展。Linux的驅(qū)動開發(fā)調(diào)試有兩種方法:(1)直接編譯到內(nèi)核,再運(yùn)行新的內(nèi)核來測試;(2)編譯為模塊的形式,單獨(dú)加載運(yùn)行調(diào)試。通常情況下設(shè)備驅(qū)動的模塊動態(tài)加載更為普遍,開發(fā)人員不必在調(diào)試過程中頻繁啟動機(jī)器就能完成設(shè)備驅(qū)動的開發(fā)工作。第七頁,共八十二頁。模塊加載與卸載模塊方式調(diào)試:(1)編譯的模塊直接插入內(nèi)核:用insmod工具;(2)從內(nèi)核中卸載模塊:用rmmod。模塊用insmod命令加載,用rmmod命令來卸載,這兩個命令分別調(diào)用module_init()和module_exit()函數(shù),還可以用lsmod命令來查看所有已加載的模塊的狀態(tài)。Linux中模塊可以用C語言編寫,用gcc命令編譯成模塊*.ko第八頁,共八十二頁。編寫HelloWorld模塊#include<linux/init.h>#include<linux/module.h>#include<linux/kernel.h>MODULE_LICENSE("DualBSD/GPL");staticint__init

hello_init(void){printk(KERN_ALERT"Hello,World!\n");return0;}staticvoid__exit

hello_exit(void){printk(KERN_ALERT"Goodbye,world!\n");}module_init(hello_init);module_exit(hello_exit);定義__init、__exit、module_init、

module_exit所必需的宏定義所有模塊相關(guān)的宏,比如MODULE_LICENSEmodule_init()、module_exit()為內(nèi)核特殊宏,分別用來定義模塊被裝載和卸載時調(diào)用的函數(shù)定義printk()中相關(guān)的宏,比如KERN_ALERT第九頁,共八十二頁。編寫HelloWorld模塊#include<linux/init.h>#include<linux/module.h>#include<linux/kernel.h>MODULE_LICENSE("DualBSD/GPL");staticinthello_init(void){printk(KERN_ALERT"Hello,World!\n");return0;}staticvoidhello_exit(void){printk(KERN_ALERT"Goodbye,world!\n");}module_init(hello_init);module_exit(hello_exit);內(nèi)核函數(shù)printk被定義在linux內(nèi)核中,他類似于標(biāo)準(zhǔn)C函數(shù)printf().用MODULE_LICENSE宏來聲明該模塊的許可協(xié)議,聲明為BSD和GPL雙重協(xié)議許可第十頁,共八十二頁。編寫HelloWorld模塊MODULE_AUTHOR(“BENSON”);//可選的MODULE_DESCRIPTION("STUDY_MODULE");//可選的第十一頁,共八十二頁。Printk函數(shù)printk(KERN_ALERT"Hello,World!\n");問:為什么不用printf()函數(shù)呢?答:在講交叉編譯工具鏈的時候,曾經(jīng)講到在編譯內(nèi)核的時候不能使用標(biāo)準(zhǔn)的C庫和其他函數(shù)庫的支持,所以不能使用printf()庫函數(shù)內(nèi)核有自己的打印函數(shù)printk(),它通過自身的運(yùn)行而不需要C庫的幫助.在使用insmod裝載之后,內(nèi)核與內(nèi)核公共函數(shù)和變量進(jìn)行連接,從而可以使用printk()函數(shù).其中KERN_ALERT宏是標(biāo)記printk()打印出字符的優(yōu)先等級的,通常有八種消息級別,定義在include/linux/kernel.h的文件中.第十二頁,共八十二頁。printk(日志級別“消息文本”);這里的日志級別通俗的說指的是對文本信息的一種輸出范圍上的指定。#defineKERN_EMERG"<0>"/*緊急事件消息,系統(tǒng)崩潰之前提示,表示系統(tǒng)不可用*/#defineKERN_ALERT"<1>"/*報(bào)告消息,表示必須立即采取措施*/#defineKERN_CRIT"<2>"/*臨界條件,通常涉及嚴(yán)重的硬件或軟件操作失敗*/#defineKERN_ERR"<3>"/*錯誤條件,驅(qū)動程序常用KERN_ERR來報(bào)告硬件的錯誤*/#defineKERN_WARNING"<4>"/*警告條件,對可能出現(xiàn)問題的情況進(jìn)行警告*/#defineKERN_NOTICE"<5>"/*正常但又重要的條件,用于提醒。常用于與安全相關(guān)的消息*/#defineKERN_INFO"<6>"/*提示信息,如驅(qū)動程序啟動時,打印硬件信息*/#defineKERN_DEBUG"<7>"/*調(diào)試級別的消息*/

第十三頁,共八十二頁。linux2.4編寫HelloWorld模塊的MakefileEXEC=helloOBJS=hello.oSRC=hello.cINCLUDE=/usr/src/linux/fs2410_2.6.8/includeCC=/usr/local/3.3.2/bin/arm-linux-gccLD=/usr/local/3.3.2/bin/arm-linux-ldMODCFLAGS=-O2-Wall-D__KERNEL__-DMODULE-I$(INCLUDE)

-march=armv4tLDFLAGS=-rall:$(EXEC)$(EXEC):$(OBJS) $(LD)$(LDFLAGS)-ohellohello.o%.o:%.c $(CC)$(MODCFLAGS)-mapcs-c$<-o$@clean: -rm-f$(EXEC)*.o*~core$@:表示完整的目標(biāo)文件,包括擴(kuò)展名$<:比目標(biāo)文件更新的依賴文件$^:表示所有的依賴文件最后生成hello.o和hello用來指定編譯內(nèi)核時所用的編譯選項(xiàng)第十四頁,共八十二頁。Linux2.6編寫HelloWorld模塊的MakefileP230ifneq($(KERNELRELEASE),)obj-m:=hello.oelseKDIR=/lib/modules/-ptx1/buildPWD:=$(shellpwd)default:$(MAKE)-C$(KDIR)M=$(PWD)modulesEndif指定了內(nèi)核源代碼的位置,其中保存有內(nèi)核的頂層makefile文件

obj-m表示要由hello.c文件編譯得到hello.o,并作為模塊編譯obj-y則表示要連接進(jìn)內(nèi)核obj-x則目標(biāo)不會被編譯。M=$(PWD)指明存放hello.c的路徑。第十五頁,共八十二頁。第十六頁,共八十二頁。M=$(PWD)指明存放hello.c的路徑。第十七頁,共八十二頁。(1)先讓FS2410P教學(xué)平臺進(jìn)入Linux環(huán)境,利用超級終端來顯示,Linux進(jìn)入命令行的模式下。(2)輸入命令cd/tmp,進(jìn)入tmp目錄,因?yàn)?tmp是在SDRAM中,可以放數(shù)據(jù)。(3)將hello.ko下載到/tmp目錄下。采用的rz命令來傳輸?shù)?,rz命令是通過Zmodem協(xié)議來傳輸?shù)?。先在教學(xué)平臺的下輸入rz命令(Linux環(huán)境下),接著點(diǎn)擊超級終端的“傳送”—>“發(fā)送文件”,在彈出的對話框中設(shè)置如下:第十八頁,共八十二頁。然后點(diǎn)擊發(fā)送。數(shù)據(jù)傳輸完后,再回車,接著通過ls來查看/tmp目錄下是否有hello.ko文件。(4)hello.ko下載成功后,接下來我們要進(jìn)行真正的加載和運(yùn)行的工作了。改變hello.ko的屬性,命令如下:chmod755hello.ko(5)加載hello.ko模塊:insmod./hello.ko

這時我們就可以看到期待已久的Hello,world了。(6).卸載驅(qū)動模塊:rmmodhello.ko卸載時就可在屏幕上看到如下信息:

Goodbye,world

第十九頁,共八十二頁。驅(qū)動程序中涉及的幾個概念設(shè)備驅(qū)動程序的設(shè)備號和入口點(diǎn)Linux系統(tǒng)通過設(shè)備號來區(qū)分不同設(shè)備。設(shè)備號由兩部分組成:主設(shè)備號和次設(shè)備號。主設(shè)備號標(biāo)識設(shè)備對應(yīng)的驅(qū)動程序。系統(tǒng)中不同的設(shè)備可以有相同的主設(shè)備號,主設(shè)備號相同的設(shè)備使用相同的驅(qū)動程序。次設(shè)備號用來區(qū)分具體驅(qū)動程序的實(shí)例。一個主設(shè)備號可能有多個設(shè)備與之對應(yīng),這多個設(shè)備正是在驅(qū)動程序內(nèi)通過次設(shè)備號來進(jìn)一步區(qū)分的。次設(shè)備號只能由設(shè)備驅(qū)動程序使用,內(nèi)核的其他部分僅將它作為參數(shù)傳遞給驅(qū)動程序。在/proc/devices中列出了系統(tǒng)中處于活動狀態(tài)設(shè)備的主設(shè)備號,所謂的活動狀態(tài)是指與該設(shè)備對應(yīng)的設(shè)備驅(qū)動已經(jīng)被系統(tǒng)內(nèi)核裝載。第二十頁,共八十二頁。/dev/字符為c表示字符設(shè)備,為b表示塊設(shè)備兩個數(shù)字對應(yīng)主設(shè)備號和次設(shè)備號對于現(xiàn)有Linux操作系統(tǒng),/dev目錄是必不可少的,這個目錄包含了所有Linux系統(tǒng)所知道的字符設(shè)備,塊設(shè)備和網(wǎng)絡(luò)設(shè)備第二十一頁,共八十二頁。/proc/devices

p233在/proc/devices中列出了系統(tǒng)中處于活動狀態(tài)設(shè)備的主設(shè)備號第二十二頁,共八十二頁。dev_t類型dev_t類型內(nèi)核用dev_t類型來保存設(shè)備編號,dev_t是個32位的數(shù),12位表示主設(shè)備號,20為表示次設(shè)備號。在實(shí)際使用中,是通過中定義的宏來轉(zhuǎn)換格式。獲得dev_t的主設(shè)備號和次設(shè)備號,應(yīng)使用以下的宏,例如:dev_tdev;MAJOR(dev);/*主設(shè)備號*/MINOR(dev);/*次設(shè)備號*/如果要將主設(shè)備號、次設(shè)備號轉(zhuǎn)換成dev_t類型,則使用以下的宏,例如:Intmajor=4,minor=3;MKDEV(intmajor,intminor)第二十三頁,共八十二頁。設(shè)備入口點(diǎn)p234設(shè)備入口點(diǎn)設(shè)備入口點(diǎn)也可以理解為“設(shè)備文件句柄”,一個設(shè)備的入口點(diǎn)和磁盤上的普通文件系統(tǒng)一樣,可以刪除(rm),移動(mv)和復(fù)制(cp)等。我們可以在文件系統(tǒng)中使用mknod命令創(chuàng)建一個設(shè)備入口點(diǎn)。在文件系統(tǒng)中創(chuàng)建了設(shè)備入口點(diǎn)并沒有代表響應(yīng)的設(shè)備驅(qū)動和硬件已經(jīng)準(zhǔn)備好,只是代表了和設(shè)備驅(qū)動通信的一部分。下面給一個創(chuàng)建字符設(shè)備入口點(diǎn)的實(shí)例:mknod/dev/testCharc

1000其中c代表字符設(shè)備,如果想創(chuàng)建塊設(shè)備則用b代替c。參數(shù)100代表該設(shè)備的主設(shè)備號,0代表該設(shè)備的次設(shè)備號。第二十四頁,共八十二頁。設(shè)備入口點(diǎn)創(chuàng)建設(shè)備的入口點(diǎn)之后,可以通過如下命令查看:ls–l/dev/testChar刪除設(shè)備入口點(diǎn)也非常簡單:rm/dev/testChar第二十五頁,共八十二頁。用戶空間和內(nèi)核空間p220設(shè)備驅(qū)動運(yùn)行在內(nèi)核空間(在一些操作系統(tǒng)的書籍里面稱為“系統(tǒng)態(tài)”),而應(yīng)用程序則運(yùn)行在用戶空間(也可稱為“用戶態(tài)”)。設(shè)備驅(qū)動程序運(yùn)行在內(nèi)核空間比應(yīng)用程序執(zhí)行的優(yōu)先級要高很多。內(nèi)核態(tài)具有最高的運(yùn)行級別,可以做任何事。應(yīng)用程序則運(yùn)行在最低級別的用戶態(tài),在這一級別處理器禁止對硬件的直接訪問和對內(nèi)存的未授權(quán)訪問。內(nèi)核空間和用戶空間分別引用不同的內(nèi)存映射,也就是程序代碼使用不同的地址空間.Linux操作系統(tǒng)通過系統(tǒng)調(diào)用和硬件中斷完成從用戶空間到內(nèi)核空間的控制轉(zhuǎn)移。第二十六頁,共八十二頁。字符設(shè)備p218字符設(shè)備:字符設(shè)備按照字符流的方式被有序訪問,像串口和鍵盤就都屬于字符設(shè)備。如果一個硬件設(shè)備是以字符流的方式被訪問的話,那就應(yīng)該將它歸于字符設(shè)備;字符設(shè)備是linux最簡單的設(shè)備,可以像文件一樣訪問,區(qū)別主要在于:普通文件可以來/回讀/寫,而字符設(shè)備只能是順序讀/寫.我們可以對其調(diào)用打開、讀取、寫和關(guān)閉。初始化字符設(shè)備時,驅(qū)動程序向linux登記,并在字符設(shè)備向量中增加一個device_struct數(shù)據(jù)結(jié)構(gòu)條目,這個設(shè)備的主設(shè)備標(biāo)識符(tty的主設(shè)備號為4)用作這個向量表的索引第二十七頁,共八十二頁。系統(tǒng)調(diào)用系統(tǒng)調(diào)用字符設(shè)備是linux最簡單的設(shè)備,可以像文件一樣訪問.所以在用戶空間中,系統(tǒng)進(jìn)程(應(yīng)用程序)對設(shè)備文件的操作通過系統(tǒng)調(diào)用來完成,如open、read、write、close等。下面通過一個簡單的例子來了解一下系統(tǒng)調(diào)用的使用:第二十八頁,共八十二頁。一個簡單的應(yīng)用程序#defineDEVICE_GPIOTEST“/dev/gpio”//設(shè)備入口點(diǎn)intmain(intargc,char*argv[]){intfd;intval=-1;fd=open(DEVICE_GPIOTEST,O_RDONLY);//打開設(shè)備if(fd<0)//fd為返回的設(shè)備文件描述字handle

{perror("cannotopendevice");exit(1);}while(1){printf("pleaseselectnumbertorunprogram\n");printf("1:ledon\n2:quit");第二十九頁,共八十二頁。一個簡單的應(yīng)用程序scanf("%d",&val);if(val==1)ioctl(fd,1,10);/*主要用于對設(shè)備進(jìn)行讀寫之外的其他控制*/elseif(val==2){close(fd);/*關(guān)閉設(shè)備*/}}return0;}第三十頁,共八十二頁。設(shè)備驅(qū)動和文件系統(tǒng)的關(guān)系

●open——打開設(shè)備準(zhǔn)備I/O操作。

open——打開設(shè)備準(zhǔn)備I/O操作。其調(diào)用格式為:intopen(char*,intaccess);

該函數(shù)返回文件描述字handle,如果返回值小于0,表示打開設(shè)備文件失敗第三十一頁,共八十二頁。close-——close()函數(shù)的作用是關(guān)閉由open()函數(shù)打開的文件,其調(diào)用格式為:intclose(inthandle);該函數(shù)關(guān)閉文件描述字handle相連的文件。

read——從設(shè)備上讀數(shù)據(jù)。對于有緩沖區(qū)的I/O操作,一般是從緩沖區(qū)里讀數(shù)據(jù)。write——往設(shè)備上寫數(shù)據(jù),對于有緩沖區(qū)的I/O操作,一般是把數(shù)據(jù)寫入緩沖區(qū)里。write()函數(shù)的調(diào)用格式為:intwrite(inthandle,void*buf,intcount);write()函數(shù)把count個字節(jié)從buf指向的緩沖區(qū)寫入與handle相連的文件中,返回值為實(shí)際寫入的字節(jié)數(shù)。7.1.1設(shè)備驅(qū)動和文件系統(tǒng)的關(guān)系第三十二頁,共八十二頁。ioctl——主要用于對設(shè)備進(jìn)行讀寫之外的其他控制。用戶空間的ioctl函數(shù)的原型為:intioctl(inffd,intcmd,…)其中的…代表可變數(shù)目的參數(shù)表,實(shí)際中是一個可選參數(shù),一般定義為:intioctl(inffd,intcmd,char*argp)其中fd為文件描述字handlecmd為命令字,不同的命令字對應(yīng)不同的操作.第三十三頁,共八十二頁。7.1.1設(shè)備驅(qū)動和文件系統(tǒng)的關(guān)系

●open——打開設(shè)備準(zhǔn)備I/O操作。

open——打開設(shè)備準(zhǔn)備I/O操作。該函數(shù)返回文件描述字handle

其調(diào)用格式為:intopen(char*,intaccess);

第三十四頁,共八十二頁。close-——close()函數(shù)的作用是關(guān)閉由open()函數(shù)打開的文件,其調(diào)用格式為:intclose(inthandle);該函數(shù)關(guān)閉文件描述字handle相連的文件。

read——從設(shè)備上讀數(shù)據(jù)。對于有緩沖區(qū)的I/O操作,一般是從緩沖區(qū)里讀數(shù)據(jù)。write——往設(shè)備上寫數(shù)據(jù),對于有緩沖區(qū)的I/O操作,一般是把數(shù)據(jù)寫入緩沖區(qū)里。write()函數(shù)的調(diào)用格式為:intwrite(inthandle,void*buf,intcount);write()函數(shù)把count個字節(jié)從buf指向的緩沖區(qū)寫入與handle相連的文件中,返回值為實(shí)際寫入的字節(jié)數(shù)。7.1.1設(shè)備驅(qū)動和文件系統(tǒng)的關(guān)系第三十五頁,共八十二頁。ioctl——主要用于對設(shè)備進(jìn)行讀寫之外的其他控制。用戶空間的ioctl函數(shù)的原型為:intioctl(inffd,intcmd,…)其中的…代表可變數(shù)目的參數(shù)表,實(shí)際中是一個可選參數(shù),一般定義為:intioctl(inffd,intcmd,char*argp)驅(qū)動程序中定義的ioctl方法原型為:int(*ioctl)(structinode*inode,structfile*intcmd,unsignedlongarg)inode和filp兩個指針對應(yīng)應(yīng)用程序傳遞的文件描述符fd、cmd不會被修改地傳遞給驅(qū)動程序,可選的參數(shù)arg則無論用戶應(yīng)用程序使用的是指針還是其他類型值,都以unsignedlong的形式傳遞給驅(qū)動。第三十六頁,共八十二頁。7.1.3設(shè)備號

linux/uclinux內(nèi)核還需要:主設(shè)備號標(biāo)識設(shè)備對應(yīng)的驅(qū)動程序。系統(tǒng)中不同的設(shè)備可以有相同的主設(shè)備號,主設(shè)備號相同的設(shè)備使用相同的驅(qū)動程序。次設(shè)備號用來區(qū)分具體驅(qū)動程序的實(shí)例。一個主設(shè)備號可能有多個設(shè)備與之對應(yīng),這多個設(shè)備正是在驅(qū)動程序內(nèi)通過次設(shè)備號來進(jìn)一步區(qū)分的。次設(shè)備號只能由設(shè)備驅(qū)動程序使用,內(nèi)核的其他部分僅將它作為參數(shù)傳遞給驅(qū)動程序。第三十七頁,共八十二頁。字符型設(shè)備主設(shè)備號的添加和注銷

字符型設(shè)備主設(shè)備號的添加和注銷分別通過調(diào)用函數(shù)register_chrdev()和unregister_chrdev()實(shí)現(xiàn),這兩個函數(shù)原型在<linux/fs.h>文件說明。externintregister_chrdev(unsignedintmajor,constchar*name,struct*fops);externintunregister_chrdev(unsignedintmajor,constchar*name);第三十八頁,共八十二頁。7.2設(shè)備驅(qū)動程序基礎(chǔ)

7.2.1設(shè)備驅(qū)動中關(guān)鍵數(shù)據(jù)結(jié)構(gòu)在linux系統(tǒng)中,設(shè)備驅(qū)動程序所提供的這組入口點(diǎn)由一個文件操作結(jié)構(gòu)進(jìn)行說明,分別是:(文件操作)數(shù)據(jù)結(jié)構(gòu)file數(shù)據(jù)結(jié)構(gòu)inode數(shù)據(jù)結(jié)構(gòu)它們定義于Linux/fs.h文件中。第三十九頁,共八十二頁。(文件操作)數(shù)據(jù)結(jié)構(gòu)由于用戶進(jìn)程是通過設(shè)備文件同硬件打交道的,所以對設(shè)備文件的操作不外乎一些系統(tǒng)調(diào)用,如open、read、write、close等。但是如何把系統(tǒng)調(diào)用和驅(qū)動程序關(guān)聯(lián)起來,這里需要一個非常關(guān)鍵的數(shù)據(jù)結(jié)構(gòu),既(文件操作)。它用來存儲驅(qū)動內(nèi)核模塊提供的對設(shè)備進(jìn)行的各種操作的函數(shù)指針。第四十頁,共八十二頁。1.數(shù)據(jù)結(jié)構(gòu)

struct{structmodule*owner;loff_t(*llseek)(structfile*,loff_t,int);ssize_t(*read)(structfile*,char*,size_t,loff_t*);ssize_t(*write)(structfile*,constchar*,size_t,loff_t*);int(*readdir)(structfile*,void*,filldir_t);unsignedint(*poll)(structfile*,structpoll_table_struct*);int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);int(*mmap)(structfile*,structvm_area_struct*);int(*open)(structinode*,structfile*);int(*flush)(structfile*);結(jié)構(gòu)體中的每一個成員都對應(yīng)著驅(qū)動內(nèi)核模塊用來處理某個請求事物的函數(shù)的地址第四十一頁,共八十二頁。int(*release)(structinode*,structfile*);int(*fsync)(structfile*,structdentry*,intdatasync);int(*fasync)(int,structfile*,int);int(*lock)(structfile*,int,struct*);ssize_t(*readv)(structfile*,conststructiovec*,unsignedlong,loff_t*);ssize_t(*writev)(structfile*,conststructiovec*,unsignedlong,loff_t*);ssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int);unsignedlong(*get_unmapped_area)(structfile*,unsignedlong,unsignedlong,unsignedlong,unsignedlong);};第四十二頁,共八十二頁。p228在simple設(shè)備驅(qū)動程序中它的結(jié)構(gòu)是如下初始化的:structsimple_fops={.owner=THIS_MODULE,.llseek=simple_llseek,.read=simple_read,.write=simple_write,.ioctl=simple_ioctl,.open=simple_open,.release=simple_release,};對simple_fops變量進(jìn)行初始化將對應(yīng)操作的函數(shù)名作為指針傳遞給相應(yīng)的成員第四十三頁,共八十二頁。在數(shù)據(jù)結(jié)構(gòu)中,指出了設(shè)備驅(qū)動程序所提供的入口點(diǎn)位置,分別是:1)structmodule*owner該成員是結(jié)構(gòu)中唯一一個不是聲明操作的成員;它是一個指向擁有這個結(jié)構(gòu)的模塊的指針.這個成員用來在它的操作還在被使用時阻止模塊被卸載.幾乎所有時間中,它被簡單初始化為THIS_MODULE,一個在<linux/module.h>中定義的宏.2)loff_t(*llseek)(structfile*,loff_t,int);llseek方法用作改變文件中的當(dāng)前讀/寫位置,并且新位置作為(正的)返回值.loff_t參數(shù)是一個"longoffset",并且就算在32位平臺上也至少64位寬.錯誤由一個負(fù)返回值指示.第四十四頁,共八十二頁。3)ssize_t(*read)(structfile*,char__user*,size_t,loff_t*);用來從設(shè)備中獲取數(shù)據(jù).當(dāng)為空時,導(dǎo)致read系統(tǒng)調(diào)用以-EINVAL(“Invalidargument”)失敗.一個非負(fù)返回值代表了成功讀取的字節(jié)數(shù)其中ssize_t為int或long型,和平臺相關(guān),__user用來聲明為用戶態(tài)4)ssize_t(*aio_read)(structkiocb*,char__user*,size_t,loff_t);初始化一個異步讀--可能在函數(shù)返回前不結(jié)束的讀操作.如果這個方法是NULL,所有的操作會由read代替進(jìn)行(同步地).第四十五頁,共八十二頁。5)ssize_t(*write)(structfile*,constchar__user*,size_t,loff_t*)發(fā)送數(shù)據(jù)給設(shè)備.如果NULL,-EINVAL返回給調(diào)用write系統(tǒng)調(diào)用的程序.如果非負(fù),返回值代表成功寫的字節(jié)數(shù).6)ssize_t(*aio_write)(structkiocb*,constchar__user*,size_t,loff_t*);初始化設(shè)備上的一個異步寫.7)int(*readdir)(structfile*,void*,filldir_t);對于設(shè)備文件這個成員應(yīng)當(dāng)為NULL;它用來讀取目錄,并且僅對文件系統(tǒng)有用.第四十六頁,共八十二頁。unsignedint(*poll)(structfile*,structpoll_table_struct*);poll方法用作查詢對一個或多個文件描述符的讀或?qū)懯欠駮枞?poll方法應(yīng)當(dāng)返回一個位掩碼指示是否非阻塞的讀或?qū)懯强赡艿?并且,可能地,提供給內(nèi)核信息用來使調(diào)用進(jìn)程睡眠直到I/O變?yōu)榭赡?如果一個驅(qū)動的poll方法為NULL,設(shè)備假定為不阻塞地可讀可寫.int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong);ioctl系統(tǒng)調(diào)用提供了發(fā)出設(shè)備特定命令的方法..如果設(shè)備不提供ioctl方法,系統(tǒng)調(diào)用將返回一個錯誤.第四十七頁,共八十二頁。int(*mmap)(structfile*,structvm_area_struct*);mmap用來請求將設(shè)備內(nèi)存映射到進(jìn)程的地址空間.如果這個方法是NULL,mmap系統(tǒng)調(diào)用返回-ENODEVint(*open)(structinode*,structfile*);該操作用來打開設(shè)備文件,也是對設(shè)備文件進(jìn)行的第一個操作,如果這個操作為空,設(shè)備打開一直成功,但是你的驅(qū)動程序不會被調(diào)用第四十八頁,共八十二頁。int(*flush)(structfile*);flush操作在進(jìn)程關(guān)閉它的設(shè)備文件描述符的拷貝時調(diào)用;它應(yīng)當(dāng)執(zhí)行(并且等待)設(shè)備的任何未完成的操作.當(dāng)前,flush在很少驅(qū)動中使用.如果flush為NULL,內(nèi)核簡單地忽略用戶應(yīng)用程序的請求.int(*release)(structinode*,structfile*);在文件結(jié)構(gòu)被釋放時引用這個操作.如同open,release可以為NULL.int(*fsync)(structfile*,structdentry*,int);這個方法是fsync系統(tǒng)調(diào)用的后端,用戶調(diào)用來刷新任何掛著的數(shù)據(jù).如果這個指針是NULL,系統(tǒng)調(diào)用返回-EINVAL.第四十九頁,共八十二頁。int(*aio_fsync)(structkiocb*,int);這是fsync方法的異步版本int(*fasync)(int,structfile*,int);這個操作用來通知設(shè)備它的FASYNC標(biāo)志的改變.異步通知是一個高級的主題,在第6章中描述.這個成員可以是NULL如果驅(qū)動不支持異步通知.int(*lock)(structfile*,int,struct*);lock方法用來實(shí)現(xiàn)文件加鎖;加鎖對常規(guī)文件是必不可少的特性,但是設(shè)備驅(qū)動幾乎從不實(shí)現(xiàn)它.第五十頁,共八十二頁。ssize_t(*readv)(structfile*,conststructiovec*,unsignedlong,loff_t*);ssize_t(*writev)(structfile*,conststructiovec*,unsignedlong,loff_t*);該操作用來對一個包含多個內(nèi)存區(qū)的單個讀或?qū)懖僮?這些系統(tǒng)調(diào)用允許它們這樣做而不必對數(shù)據(jù)進(jìn)行額外拷貝.如果這些函數(shù)指針為NULL,read和write方法被調(diào)用(可能多于一次).ssize_t(*sendfile)(structfile*,loff_t*,size_t,read_actor_t,void*);這個方法實(shí)現(xiàn)sendfile系統(tǒng)調(diào)用的讀,使用最少的拷貝從一個文件描述符搬移數(shù)據(jù)到另一個.例如,它被一個需要發(fā)送文件內(nèi)容到一個網(wǎng)絡(luò)連接的web服務(wù)器使用.設(shè)備驅(qū)動常常使sendfile為NULL.ssize_t(*sendpage)(structfile*,structpage*,int,size_t,loff_t*,int);sendpage是sendfile的另一半;它由內(nèi)核調(diào)用來發(fā)送數(shù)據(jù),一次一頁,到對應(yīng)的文件.設(shè)備驅(qū)動實(shí)際上不實(shí)現(xiàn)sendpage.第五十一頁,共八十二頁。unsignedlong(*get_unmapped_area)(structfile*,unsignedlong,unsignedlong,unsignedlong,unsignedlong);這個方法的目的是在進(jìn)程的地址空間找一個合適的位置來映射在底層設(shè)備上的內(nèi)存段中.這個任務(wù)通常由內(nèi)存管理代碼進(jìn)行;這個方法存在為了使驅(qū)動能強(qiáng)制特殊設(shè)備可能有的任何的對齊請求.大部分驅(qū)動可以置這個方法為NULL.int(*check_flags)(int)這個方法允許模塊檢查傳遞給fnctl(F_SETFL...)調(diào)用的標(biāo)志.int(*dir_notify)(structfile*,unsignedlong);第五十二頁,共八十二頁。2.

inode數(shù)據(jù)結(jié)構(gòu)inode譯成中文就是索引節(jié)點(diǎn)。每個存儲設(shè)備或存儲設(shè)備的分區(qū)(存儲設(shè)備是硬盤、軟盤、U盤......)被格式化為文件系統(tǒng)后,應(yīng)該有兩部份,一部份是inode,另一部份是Block,Block是用來存儲數(shù)據(jù)用的。而inode呢,就是用來存儲這些數(shù)據(jù)的信息,這些信息包括文件大小、屬主、歸屬的用戶組、讀寫權(quán)限等。inode為每個文件進(jìn)行信息索引,所以就有了inode的數(shù)值。操作系統(tǒng)根據(jù)指令,能通過inode值最快的找到相對應(yīng)的文件。做個比喻,比如一本書,存儲設(shè)備或分區(qū)就相當(dāng)于這本書,Block相當(dāng)于書中的每一頁,inode就相當(dāng)于這本書前面的目錄,一本書有很多的內(nèi)容,如果想查找某部份的內(nèi)容,我們可以先查目錄,通過目錄能最快的找到我們想要看的內(nèi)容。雖然不太恰當(dāng),但還是比較形象。第五十三頁,共八十二頁。當(dāng)我們用ls查看某個目錄或文件時,如果加上-i參數(shù),就可以看到inode節(jié)點(diǎn)了;比如比如hello.c文件的inode值為444676第五十四頁,共八十二頁。2.

inode數(shù)據(jù)結(jié)構(gòu)p222文件系統(tǒng)處理的文件所需要的信息在inode(索引結(jié)點(diǎn))數(shù)據(jù)結(jié)構(gòu)中。Inode數(shù)據(jù)結(jié)構(gòu)提供了關(guān)于特殊設(shè)備文件/dev/DriverName的信息,定義如下:

structinode稱做索引節(jié)點(diǎn)數(shù)據(jù)結(jié)構(gòu),inode(索引結(jié)點(diǎn))數(shù)據(jù)結(jié)構(gòu)定義如下:structinode{structhlist_nodei_hash;structlist_headi_list;structlist_headi_sb_list;structlist_headi_dentry;unsignedlongi_ino;atomic_ti_count;umode_ti_mode;…….}第五十五頁,共八十二頁。Inode結(jié)構(gòu)包含了大量有關(guān)文件的信息,但通常情況下對設(shè)備驅(qū)動開發(fā)比較有用的成員有下面兩個dev_ti_rdev;//該成員包含了設(shè)備編號structcdev*i_cdev;//指向字符設(shè)備文件的指針說明:當(dāng)inode指向一個字符設(shè)備文件時,該成員包含了指向structcdev結(jié)構(gòu)的指針,其中cdev結(jié)構(gòu)是字符設(shè)備結(jié)構(gòu)體第五十六頁,共八十二頁。cdev結(jié)構(gòu)在Linux2.6內(nèi)核中一個字符設(shè)備用cdev結(jié)構(gòu)來描述,其定義如下:structcdev{structkobjectkobj;

structmodule*owner;//所屬模塊conststruct*ops;//文件操作結(jié)構(gòu)

structlist_headlist;

dev_tdev;//設(shè)備號unsignedintcount;};第五十七頁,共八十二頁。3.file數(shù)據(jù)結(jié)構(gòu)設(shè)備驅(qū)動程序中,另一個非常重要的數(shù)據(jù)結(jié)構(gòu)就是File結(jié)構(gòu),它不同于應(yīng)用程序空間的FILE指針,FILE指針定義在C庫中因而不會出現(xiàn)在內(nèi)核代碼中,而sturctfile只出現(xiàn)在內(nèi)核代碼中,從不出現(xiàn)在用戶程序中內(nèi)核用inode結(jié)構(gòu)表示具體的文件,而file結(jié)構(gòu)表示打開的文件描述符對于單個文件,可能會有許多個表示打開的文件描述符file結(jié)構(gòu),但是它們都指向了單個的inode結(jié)構(gòu),所以file結(jié)構(gòu)和inode結(jié)構(gòu)是不同的.第五十八頁,共八十二頁。3.file數(shù)據(jù)結(jié)構(gòu)structfile{structlist_head f_list;//打開的文件形成一個列表structdentry *f_dentry;//指向相關(guān)目錄項(xiàng)的指針structvfsmount*f_vfsmnt;//執(zhí)行VFS掛載點(diǎn)的指針struct *f_op;//執(zhí)行文件操作的指針atomic_t f_count;//使用該結(jié)構(gòu)的進(jìn)程數(shù)unsignedint f_flags;//文件打開的標(biāo)志,如讀寫等mode_t f_mode;//文件打開的模式3.file數(shù)據(jù)結(jié)構(gòu)第五十九頁,共八十二頁。loff_t f_pos;//文件的當(dāng)前位置unsignedlongf_reada,f_ramax,f_raend,f_ralen,f_rawin;/*預(yù)讀標(biāo)志、要預(yù)讀的最多頁面數(shù)、上次預(yù)讀后的文件指針、預(yù)讀的字節(jié)數(shù)以及預(yù)讀的頁面數(shù)*/structfown_struct f_owner;//文件的所有者unsignedint f_uid,f_gid;//用戶的UID和GIDint f_error;//網(wǎng)絡(luò)寫操作錯誤碼unsignedlong f_version;//版本號void *private_data;//tty驅(qū)動程序使用structkiobuf *f_iobuf;long f_iobuf_lock;};第六十頁,共八十二頁。7.2.2字符設(shè)備驅(qū)動開發(fā)p2287.2.2設(shè)備驅(qū)動程序的開發(fā)流程

(1)硬件接口設(shè)計(jì)或使用嵌入式處理器的生產(chǎn)商提供參考接口電路。(2)設(shè)計(jì)所要實(shí)現(xiàn)的文件操作,定義結(jié)構(gòu)。(3)實(shí)現(xiàn)所需的文件操作調(diào)用,如read、write等。(2)實(shí)現(xiàn)初始化模塊函數(shù)__init,其中定義設(shè)備號。(3)實(shí)現(xiàn)初始化函數(shù),其中實(shí)現(xiàn)驅(qū)動的注冊。(6)實(shí)現(xiàn)中斷服務(wù),并用request_irq向內(nèi)核注冊。(7)實(shí)現(xiàn)卸載模塊函數(shù)__exit,完成驅(qū)動的注銷,釋放設(shè)備號(7)編譯該驅(qū)動程序到內(nèi)核中,或者用insmod命令加載模塊。(8)測試該設(shè)備,編寫應(yīng)用程序,對驅(qū)動程序進(jìn)行測試。第六十一頁,共八十二頁。定義結(jié)構(gòu)p228在simple設(shè)備驅(qū)動程序中它的結(jié)構(gòu)是如下初始化的:structsimple_fops={.owner=THIS_MODULE,.llseek=simple_llseek,.read=simple_read,.write=simple_write,.ioctl=simple_ioctl,.open=simple_open,.release=simple_release,};對simple_fops變量進(jìn)行初始化將對應(yīng)操作的函數(shù)名作為指針傳遞給相應(yīng)的成員第六十二頁,共八十二頁。7.2.2字符設(shè)備驅(qū)動開發(fā)p2287.2.2設(shè)備驅(qū)動程序的開發(fā)流程

(1)硬件接口設(shè)計(jì)或使用嵌入式處理器的生產(chǎn)商提供參考接口電路。(2)設(shè)計(jì)所要實(shí)現(xiàn)的文件操作,定義結(jié)構(gòu)。(3)實(shí)現(xiàn)所需的文件操作調(diào)用,如open、read、write等。(2)實(shí)現(xiàn)初始化模塊函數(shù)__init,其中定義設(shè)備號。(3)實(shí)現(xiàn)初始化函數(shù),其中實(shí)現(xiàn)驅(qū)動的注冊。(6)實(shí)現(xiàn)中斷服務(wù),并用request_irq向內(nèi)核注冊。(7)實(shí)現(xiàn)卸載模塊函數(shù)__exit,完成驅(qū)動的注銷,釋放設(shè)備號(7)編譯該驅(qū)動程序到內(nèi)核中,或者用insmod命令加載模塊。(8)測試該設(shè)備,編寫應(yīng)用程序,對驅(qū)動程序進(jìn)行測試。第六十三頁,共八十二頁。實(shí)現(xiàn)所需的文件操作調(diào)用p228staticintdevice_open(structinode*inode,structfile*file)

{

printk(“simpledeviceisopen\n”);//打印一句話try_module_get(THIS_MODULE);……return0;

}

函數(shù):try_module_get()--如果模塊已經(jīng)插入內(nèi)核,則遞增該模塊引用計(jì)數(shù),每次加1;如果該模塊還沒有插入內(nèi)核,則返回0表示出錯。

第六十四頁,共八十二頁。實(shí)現(xiàn)所需的文件操作調(diào)用staticintdevice_release(structinode*inode,structfile*file)

{

printk(“Simpledevice_releasecall\n");

module_put(THIS_MODULE);……return0;

}函數(shù):module_put()--與try_module_get()相對應(yīng),該模塊引用計(jì)數(shù)減1;如果該模塊還沒有插入內(nèi)核,則返回0表示出錯第六十五頁,共八十二頁。7.2.2字符設(shè)備驅(qū)動開發(fā)7.2.2設(shè)備驅(qū)動程序的開發(fā)流程

(1)硬件接口設(shè)計(jì)或使用嵌入式處理器的生產(chǎn)商提供參考接口電路。(2)設(shè)計(jì)所要實(shí)現(xiàn)的文件操作,定義結(jié)構(gòu)。(3)實(shí)現(xiàn)所需的文件操作調(diào)用,如read、write等。(2)實(shí)現(xiàn)初始化模塊函數(shù)__init,其中定義設(shè)備號。(3)實(shí)現(xiàn)初始化函數(shù),其中實(shí)現(xiàn)驅(qū)動的注冊。(6)實(shí)現(xiàn)中斷服務(wù),并用request_irq向內(nèi)核注冊。(7)實(shí)現(xiàn)卸載模塊函數(shù)__exit,完成驅(qū)動的注銷,釋放設(shè)備號(7)編譯該驅(qū)動程序到內(nèi)核中,或者用insmod命令加載模塊。(8)測試該設(shè)備,編寫應(yīng)用程序,對驅(qū)動程序進(jìn)行測試。第六十六頁,共八十二頁。1)設(shè)備主設(shè)備號的添加和注銷p225設(shè)備驅(qū)動在加載時首先需要調(diào)用入口函數(shù)module_init(),該函數(shù)完成設(shè)備驅(qū)動的初始化工作,比如分配設(shè)備號,驅(qū)動程序的注冊,寄存器置位、結(jié)構(gòu)體賦值等。第六十七頁,共八十二頁。1)設(shè)備主設(shè)備號的添加和注銷p226建立字符設(shè)備以前,必須分配設(shè)備號??梢允褂胷egister_chrdev_region函數(shù)完成,該函數(shù)原型如下:intregister_chrdev_region(dev_tfirst,unsignedintcount,char*name)First:是要分配的設(shè)備號范圍的起始值Count:是請求的連續(xù)設(shè)備號的數(shù)目Name:是與該編號范圍關(guān)聯(lián)的設(shè)備名稱,也就是在/proc/devices和sysfh中出現(xiàn)的名稱。如何能夠確定起始范圍?第六十八頁,共八十二頁。實(shí)際上,Linux提供了動態(tài)分配設(shè)備號的函數(shù),通過這個函數(shù),內(nèi)核可以為我們分配合適的設(shè)備號。函數(shù)原型如下:intalloc_chrdev_region(dev_t*dev,unsignedintfirsetminor,unsignedintcount,char*name)該函數(shù)的返回值為<0,表示不能獲得設(shè)備號dev:用于輸出的參數(shù),保存已分配范圍的第一個編號。Firstminor:是要使用的被請求的第一個次設(shè)備號,通常設(shè)置為0。Count:是請求的連續(xù)設(shè)備號的數(shù)目Name:是與該編號范圍關(guān)聯(lián)的設(shè)備名稱第六十九頁,共八十二頁。動態(tài)分配設(shè)備號例如:#defineCDRIVER_NAME“simple_chrev”dev_tsimple_dev;intresult,count=1,CDRIVER_MAJOR=0,CDRIVER_MINOR=0;result=alloc_chrdev_region(&simple_dev,CDRIVER_MINOR,count,CDRIVER_NAME)CDRIVER_MAJOR=MAJOR(simple_dev);If(result<0){printk(KERN_ERR“cannotgetmajor%d\n",CDRIVER_MAJOR);}第七十頁,共八十二頁。將不需要的資源及時釋放是一個好的編程習(xí)慣。在不使用設(shè)備號時,也應(yīng)該把它釋放,只需調(diào)用unregister_chrdev_region函數(shù)即可。函數(shù)原型如下:Voidunregister_chrdev_region(dev_tfirst,unsignedcount)例如:staticvoid__exit

simple_exit(void){unregister_chrdev_region(simple_dev,count)}第七十一頁,共八十二頁。7.2.2字符設(shè)備驅(qū)動開發(fā)7.2.2設(shè)備驅(qū)動程序的開發(fā)流程

(1)硬件接口設(shè)計(jì)或使用嵌入式處理器的生產(chǎn)商提供參考接口電路。(2)設(shè)計(jì)所要實(shí)現(xiàn)的文件操作,定義結(jié)構(gòu)。(3)實(shí)現(xiàn)所需的文件操作調(diào)用,如read、write等。(2)實(shí)現(xiàn)初始化模塊函數(shù)__init,其中定義設(shè)備號。(3)實(shí)現(xiàn)初始化函數(shù),其中實(shí)現(xiàn)設(shè)備驅(qū)動的注冊。(6)實(shí)現(xiàn)中斷服務(wù),并用request_irq向內(nèi)核注冊。(7)實(shí)現(xiàn)卸載模塊函數(shù)__exit,完成驅(qū)動的注銷,釋放設(shè)備號(7)編譯該驅(qū)動程序到內(nèi)核中,或者用insmod命令加載模塊。(8)測試該設(shè)備,編寫應(yīng)用程序,對驅(qū)動程序進(jìn)行測試。第七十二頁,共八十二頁。linux2.4驅(qū)動的注冊和卸載在初始化中最重要的一個工作就是向內(nèi)核注冊該設(shè)備.在linux2.4內(nèi)核中,對于字符設(shè)備調(diào)用register_chrdev()完成注冊,對于塊設(shè)備需要調(diào)用register_blkdev()完成注冊。注冊成功后,該設(shè)備獲得了系統(tǒng)分配的主設(shè)備號、自定義的次設(shè)備號,并建立起與文件系統(tǒng)的關(guān)聯(lián)。對于PCI、USB設(shè)備的注冊與此略有不同,將在后面的章節(jié)中介紹。設(shè)備驅(qū)動在卸載時需要回收相應(yīng)的資源,令設(shè)備的響應(yīng)寄存器值置位并從系統(tǒng)中注銷該設(shè)備,字符設(shè)備調(diào)用unregister_chrdev()、塊設(shè)備調(diào)用unregister_blkdev()。第七十三頁,共八十二頁。register_chrdev函數(shù)的定義intregister_chrdev(unsignedintmajor,constchar*name,struct*fops);major是為設(shè)備驅(qū)動程序向系統(tǒng)申請的主設(shè)備號,如果為0則系統(tǒng)為此驅(qū)動程

溫馨提示

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

最新文檔

評論

0/150

提交評論