1Linu設(shè)備驅(qū)動程序簡介_第1頁
1Linu設(shè)備驅(qū)動程序簡介_第2頁
1Linu設(shè)備驅(qū)動程序簡介_第3頁
已閱讀5頁,還剩8頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、Linux設(shè)備驅(qū)動程序簡介The System Call InterfaceConcurrency rnulli tasking帕 hrciiungcondmfICotinectivtlyVirtual memoryTtyi & device accessi" *- Pmcan managenenlf Memory ;mafiagBmmsuixsyamsFiles and din:iheVFSMums snpigmcntdcfNetwork tubsyitefTidrnncuIBlocfc dfiviceiIF dnvsnI I| Momoryrnsfugar QQruiii

2、iniSMn吊 supp&tTinitenwcy Dirts & CDi Conwtei. Network efcFinterlacesI 如 IriM 欣岀 Eltefumdl 細(xì)Lin uxKernel系統(tǒng)架構(gòu)圖、驅(qū)動程序的特點是應(yīng)用和硬件設(shè)備之間的一個軟件層。這個軟件層一般在內(nèi)核中實現(xiàn)設(shè)備驅(qū)動程序的作用在于提供機制,而不是提供策略,編寫訪問硬件的內(nèi) 核代碼時不要給用戶強加任何策略o機制:驅(qū)動程序能實現(xiàn)什么功能。o策略:用戶如何使用這些功能。、設(shè)備驅(qū)動分類和內(nèi)核模塊設(shè)備驅(qū)動類型。Linux系統(tǒng)將設(shè)備驅(qū)動分成三種類型o字符設(shè)備o塊設(shè)備o網(wǎng)絡(luò)設(shè)備內(nèi)核模塊:內(nèi)核模塊是內(nèi)核提供的一

3、種可以動態(tài)加載功能單元來擴展內(nèi)核 功能的機制,類似于軟件中的插件機制。這種功能單元叫內(nèi)核模塊。通常為每個驅(qū)動創(chuàng)建一個不同的模塊,而不在一個模塊中實現(xiàn)多個設(shè)備驅(qū) 動,從而實現(xiàn)良好的伸縮性和擴展性。三、字符設(shè)備字符設(shè)備是個能夠象字節(jié)流(比如文件)一樣訪問的設(shè)備,由字符設(shè)備驅(qū) 動程序來實現(xiàn)這種特性。通過/dev下的字符設(shè)備文件來訪問。字符設(shè)備 驅(qū)動程序通常至少需要實現(xiàn) open、close、read和write等系統(tǒng)調(diào)用所對 應(yīng)的對該硬件進行操作的功能函數(shù)。*應(yīng)用程序調(diào)用systemcall (系統(tǒng)調(diào)用),例如:read、write,將會導(dǎo)致 操作系統(tǒng)執(zhí)行上層功能組件的代碼,這些代碼會處理內(nèi)核的一些

4、內(nèi)部事 務(wù),為操作硬件做好準(zhǔn)備,然后就會調(diào)用驅(qū)動程序中實現(xiàn)的對硬件進行物 理操作的函數(shù),從而完成對硬件的驅(qū)動,然后返回操作系統(tǒng)上層功能組件 的代碼,做好內(nèi)核內(nèi)部的善后事務(wù),最后返回應(yīng)用程序。因為應(yīng)用程序必須使用/dev目錄下的設(shè)備文件(參見open調(diào)用的第1個 參數(shù)),所以該設(shè)備文件必須事先創(chuàng)建。誰創(chuàng)建設(shè)備文件呢?大多數(shù)字符設(shè)備是個只能順序訪問的數(shù)據(jù)通道,不能前后移動訪問指針, 這點和文件不同。比如串口驅(qū)動,只能順序的讀寫設(shè)備。然而,也存在和 數(shù)據(jù)區(qū)或者文件特性類似的字符設(shè)備,訪問它們時可前后移動訪問指針。 例如framebuffer設(shè)備就是這樣一個設(shè)備,應(yīng)用程序可以用mma或lseek 訪問

5、圖象的各個區(qū)域。四、塊設(shè)備-塊設(shè)備通常是按照塊為單位來訪問數(shù)據(jù),比如一塊為512字節(jié)。*塊設(shè)備也是通過/dev目錄下的文件系統(tǒng)節(jié)點來訪問。塊設(shè)備和字符設(shè)備 的區(qū)別僅僅在于內(nèi)核內(nèi)部管理數(shù)據(jù)的方式, 也就是內(nèi)核和驅(qū)動程序的接口 不同。塊設(shè)備除了給內(nèi)核提供和字符設(shè)備一樣的接口外,還提供了專門面向塊設(shè)備的接口,塊設(shè)備的接口必須支持掛裝文件系統(tǒng),通過此接口,塊設(shè)備能夠容納文件系統(tǒng),因此應(yīng)用程序一般通過文件系統(tǒng)來訪問塊設(shè)備上的內(nèi) 容。*文件系統(tǒng)可能是除驅(qū)動程序外Linux系統(tǒng)中最重要的模塊類型,與塊設(shè)備 驅(qū)動程序聯(lián)系緊密。五、網(wǎng)絡(luò)設(shè)備驅(qū)動和網(wǎng)絡(luò)接口*網(wǎng)絡(luò)設(shè)備驅(qū)動不同于字符設(shè)備和塊設(shè)備,不在/dev下以文件

6、節(jié)點為代表,而是通過單獨的網(wǎng)絡(luò)接口(ethO、eth1)來代表。任何網(wǎng)絡(luò)事務(wù)都要經(jīng)過一個網(wǎng)絡(luò)接口,即一個能夠和其它主機交換數(shù)據(jù)的 設(shè)備。通常接口代表一個硬件設(shè)備(如網(wǎng)卡),但也可能是個純軟件設(shè)備。內(nèi)核和網(wǎng)絡(luò)驅(qū)動程序間的通訊完全不同于內(nèi)核和字符設(shè)備以及塊設(shè)備驅(qū) 動程序之間的通信,內(nèi)核調(diào)用一套和數(shù)據(jù)包傳輸相關(guān)的函數(shù)。六、設(shè)備文件和設(shè)備驅(qū)動設(shè)備文件是文件系統(tǒng)上的一個節(jié)點,是一種特殊的文件,叫做設(shè)備文件。 每個設(shè)備文件在用戶空間代表了一個設(shè)備。設(shè)備文件一般存在/dev目錄下,用mknod命令創(chuàng)建。設(shè)備文件有主、次 設(shè)備號與其關(guān)聯(lián)。設(shè)備文件是用戶應(yīng)用程序和設(shè)備驅(qū)動的接口。 應(yīng)用程序一般只能通過設(shè)備 文件

7、來使用設(shè)備驅(qū)動的功能。字符和塊設(shè)備驅(qū)動必須有相應(yīng)的設(shè)備文件來對應(yīng)。很明顯,操作系統(tǒng)內(nèi)部不可能用設(shè)備文件名來與物理設(shè)備及其驅(qū)動進行綁定。 其 實,操作系統(tǒng)內(nèi)部是用設(shè)備號來與物理設(shè)備及其驅(qū)動進行綁定的。 習(xí)慣上,用主 設(shè)備號與驅(qū)動進行關(guān)聯(lián),用次設(shè)備號與具有相同驅(qū)動的不同物理設(shè)備關(guān)聯(lián) (例如: 2個硬盤)。denni sde nni s-desktop:$ls-l/dev/sda-cbrw-rw-Irootdisk 8,02010-04-1313:38/dev/sdabrw-rw-1rootdiskbrw-rw-1rootdisk8,162010-04-1313:38/dev/sdb8,32 201

8、0-04-1313:38/dev/sdc當(dāng)用戶程序運行open("/dev/ttyS0", )時,因為設(shè)備文件/dev/ttyS0有一個設(shè) 備號與其關(guān)聯(lián),因此操作系統(tǒng)可以獲知應(yīng)用程序想操控的設(shè)備的設(shè)備號,而操作系統(tǒng)內(nèi)部又將設(shè)備號與物理設(shè)備及其驅(qū)動進行了綁定,因此操作系統(tǒng)就可以知道 應(yīng)該調(diào)用哪一個驅(qū)動去控制哪一個設(shè)備。當(dāng)然這一切的前提是,操作系統(tǒng)內(nèi)部要將設(shè)備號與物理設(shè)備及其驅(qū)動進行綁定,那么操作系統(tǒng)內(nèi)部是用什么手段完成這 種綁定關(guān)系的呢?實際上,在操作系統(tǒng)內(nèi)部存在一個結(jié)構(gòu)體鏈表 (就是上圖中的 Chardevicelist ,以后稱它為設(shè)備鏈表),鏈表的每個節(jié)點代表一個綁定關(guān)

9、系(也 就是說:節(jié)點至少含有2個字段,1個用于記錄設(shè)備號,另1個用于記錄尋找驅(qū) 動的信息,通常是一個指向驅(qū)動函數(shù)結(jié)構(gòu)體的指針)。那么是誰生成節(jié)點并將它 鏈入鏈表的呢?當(dāng)然是驅(qū)動程序! 七、構(gòu)造和運行模塊1、KernelModule 的特點模塊只是先注冊自己以便服務(wù)于將來的某個請求,然后就立即結(jié)束。模塊可以是實現(xiàn)驅(qū)動程序,文件系統(tǒng),或者其他功能。*加載模塊后,模塊運行在內(nèi)核空間,和內(nèi)核鏈接為一體。2、模塊與內(nèi)核的接口函數(shù)(除掉read、write等功能函數(shù))生成節(jié)點并將它鏈入設(shè)備鏈表這個操作由驅(qū)動中的函數(shù)實現(xiàn),這些函數(shù)什么時機運行呢?當(dāng)然最合適的時機是內(nèi)核加載模塊(in smod模塊)的時候。函

10、數(shù)init_module :內(nèi)核加載模塊的時候調(diào)用。主要功能是:為以后使用 模塊里的函數(shù)和變量預(yù)先做準(zhǔn)備函數(shù)cleanup_module :模塊的第二個入口點,內(nèi)核在模塊即將卸載之前 調(diào)用它。3、操作模塊相關(guān)的命令* insmod:加載模塊。后面參數(shù)是模塊文件名。#i nsmod/lib/modules/hello.koHello,world rmmod卸載模塊。后面參數(shù)是模塊名稱#rmmodhello Goodbye,cruelworld« lsmod :列出當(dāng)前內(nèi)核使用的模塊?;蛘卟榭?proc/modules文件。« depmod 掃描 /lib/modules/&l

11、t;kernelversion>/目錄下的所有內(nèi)核模塊,從而給內(nèi)核模塊生成依賴文件。o 生成 /lib/modules/vkernelversio n>/modules.dep<kernelversion>是當(dāng)前運行內(nèi)核的版本號* modprobe:根據(jù)modules.dep文件探測并加載內(nèi)核模塊 名稱, 處。自動尋找適合的模塊文件,并進行加載。注意和可以自動尋找模塊文件并加載。 自動尋找并加載依賴的模塊。文件,其中只需要給出模塊insmod的不同之/Iib/modules/s3c24xx_button s.ko:/lib/modules/leds.ko /lib/mo

12、dules/leds.ko:#lsmodModule#modprobes3c24xx_butt onsleds in itializedbutt onsin itialized#lsmodModules3c24xx_butto nsleds#rmmodledsrmmod:leds:Resourcetemporarily un available#rmmods3c24xx_butt onsbutt on sdriver uni oaded#lsmodModuleleds#rmmodledsledsdriver uni oaded#lsmodModule#in smods3c24xx_butt o

13、nss3c24xx_butt on s:U nknown symbolledoffs3c24xx_butt on s:U nknown symbolled onin smod:ca nn oti nsert'/lib/modules/s3c24xx_butt on s.ko':U nknown symboli nm odule(-1):Nosuchfileordirectory5944 0SizeSizeUsedbyUsedby3592 1s3c24xxSize Usedby 3592 0Size UsedbyNottai ntedNottai ntedbutt onsNott

14、ai ntedNottai ntedbutt on s.ko file name:s3c24xx butt on s.ko* modinfo :查看模塊文件的基本信息denni sde nni s-desktop:/work/studydriver/butt on s$mod in fos3c24xx_lice nse: descripti on: author: depe nds: vermagic:GPLS3C2410/S3C2440BUTTONDriver2.6.22.6mod unloadARMv4YangZhu E-mail:4、內(nèi)核模塊的編譯方法內(nèi)核源碼樹:指的是內(nèi)核源代碼tar包

15、解壓縮后形成的目錄(包含其下級所有目 錄和文件)已編譯內(nèi)核源碼樹:指的是已經(jīng)成功生成過內(nèi)核的內(nèi)核源碼樹(即:已經(jīng)成功執(zhí)行過makeulmage的內(nèi)核源碼樹)驅(qū)動大多都編譯為模塊,2.6內(nèi)核中要想編譯模塊,必須先存在已經(jīng)成功編譯了 的內(nèi)核源碼樹(即:已編譯內(nèi)核源碼樹),且該源碼樹編譯出來的內(nèi)核就是該模 塊即將運行在其上的內(nèi)核。編譯方法1:* 編寫 Makefile : obj-m:=hello.o* 編譯命令:make- C內(nèi)核源碼樹目錄 M='pwd'moduleso例如:denn isde nn is-desktop:/work/studydriver/examples/mi

16、sc-modules$make-C/ work/system/li nux-2.6.22.6/M='pwd'modules對該make命令的解釋:要想編譯內(nèi)核模塊,只需要在內(nèi)核源碼樹的頂層目錄下輸入 makemodules來編譯 Makefile中的modules目標(biāo)即可,剩下的事情,由內(nèi)核構(gòu)造系統(tǒng)全權(quán)替我們處 理。但因為目前不處于內(nèi)核源碼樹的頂層目錄,并且當(dāng)前目錄下的 Makefile也 沒有modules目標(biāo),因此使用-C參數(shù)來告知make程序需要在執(zhí)行之前切換到 /目錄。此外,因為模塊的源代碼在當(dāng)前目錄中,不在內(nèi)核源碼樹中,因此需要使用M變量(該變量是內(nèi)核構(gòu)造系統(tǒng)的變量)

17、告知內(nèi)核構(gòu)造系統(tǒng),編譯模塊所需的源代碼以及Makefile在當(dāng)前目錄(/work/studydriver/examples/misc-modules ) 中來找,而且最終生成的模塊 ko文件也要放在當(dāng)前目錄中。編譯方法2:編寫Makefile如下:ifeq($(KERNELRELEASE),)PWD:=$(shellpwd)modules:$(MAKE)-C$(KERNELDIR)M=$(PWD)modulesmodulesnstall:$(MAKE)-C$(KERNELDIR)M=$(PWD)modules_i nstallclea n:rm-rf*.o*core.depe nd.*.cmd

18、*.ko*.mod.c.tmp_versio ns .PHONY:modulesmodules_i nstallclea nelseobj-m:=hello.oen dif«編譯命令:make對該Makefile的解釋:當(dāng) make時,因為變量 KERNELRELEASE未賦值,因此 ifeq($(KERNELRELEASE),) 為真,于是變量KERNELDI被賦值為內(nèi)核源碼樹目錄/work/system/linux-2.6.22.6 ,變量 PWD被賦值為當(dāng)前目錄 /work/studydriver/examples/misc-modules,然后執(zhí)行找到的第 1 個目標(biāo)modu

19、les,從而執(zhí)行命令make-C/work/system/li nux-2.6.22.6M=/work/studydriver/exampl es/misc-modulesmodules,而當(dāng)該命令執(zhí)行以調(diào)用內(nèi)核構(gòu)造系統(tǒng)的時候,內(nèi)核構(gòu)造系統(tǒng)會為變量 KERNELRELEA賦值,從而它不再為空,從而當(dāng)前目錄下的Makefile就變成了只有一行:obj-m:=hello.o 。此時情況與編譯方法1的情況完全相同,因此2 種編譯方法得到了相同的結(jié)果。最后將得到編譯好的模塊hello.ko5、簡單的內(nèi)核模塊例子* 初始化函數(shù):hello_init ,使用宏 modulenit 來聲明。* 銷毀函數(shù):h

20、ello_exit ,使用宏 module_exit來聲明。模塊LICENSE信息,使用宏MODULE_LICENSE說明1#in clude<li nux/in it.h>2#i nclude<li nux/module.h>3MODULE_LICENSE("DualBSD/GPL");45statici nthello_i nit(void)6 一7prin tk(KERN_ALERT"Hello,worldn");8return。;91011staticvoidhello_exit(void)1213prin tk(KERN

21、_ALERT"Goodbye,cruelworldn");141516module_i ni t(hello_i nit);17module_exit(hello_exit);模塊執(zhí)行結(jié)果:#in smodhello.koHello,world #rmmodhello Goodbye,cruelworld&帶參數(shù)的內(nèi)核模塊例子*可以給模塊在加載的時候傳遞參數(shù)使用宏MODULE_PARM量名,變量類型,權(quán)限)來聲明參數(shù)。變量有如下類 型: short、ushort、int、uint、long、ulong、charp、bool 使用方法:in smodhellp.koh

22、owma ny=3whom= “ Yan gZhu" 1#in clude<li nux/in it.h>2#i nclude<li nu x/module.h> 3#i ncludevli nu x/moduleparam.h>4staticchar*whom="world"5statici nthowma ny =1;6module_param(howma ny,i nt,SRUGO|SWUSR); 7module_param(whom,charp,SRUGO);89statici nthello_i nit(void)10111

23、213,whom);1415in ti;for(i=O;i<howma ny;i+)prin tk(KERN_ALERT"(%d)Hello,%sn",ireturn0;1617staticvoidhello_exit(void)1819prin tk(KERN_ALERT"howma nyis%d,whomis%sn",howma ny,whom);20prin tk(KERN_ALERT"Goodbye,cruelworldn");212223module_i ni t(hello_i nit);24module_exit(

24、hello_exit);模塊執(zhí)行結(jié)果:#in smodhellop.ko hellop:modulelice nse' un specified'ta in tsker nel. (0)Hello,world#i nsmodhellop.kohowma ny=3whom="Ya ngZhu" (0)Hello,Ya ngZhu(1)Hello,Ya ngZhu Hello,Ya ngZhu #rmmodhellophowma nyis3,whomisYa ngZhu Goodbye,cruelworld/sys 目錄,MODULE_PARM/sys目錄下文件

25、的內(nèi)容4096May 322:09howma4096May 322:09whom-模塊運行期間,參數(shù)變量會以文件的形式出現(xiàn)在 宏中的權(quán)限指定了該文件的權(quán)限??梢酝ㄟ^改變 來改變參數(shù)變量的值#i nsmodhellop.kohowma ny=3whom="Ya ngZhu"(0)Hello,Ya ngZhu(1)Hello,Ya ngZhu Hello,Ya ngZhu#ls/sys/module/hellop/parameters/-l-rw-r-r-1rootrootny-r-r-r-1rootroot #cat/sys/module/hellop/parameters/

26、howma ny3#cat/sys/module/hellop/parameters/whom YangZhu #echo10>/sys/module/hellop/parameters/howma ny#echoYa ngYon g>/sys/module/hellop/parameters/whom-sh:ca nno tcreate/sys/module/hellop/parameters/whom:Permissio nden ied#rmmodhellophowma nyis10,whomisYa ngZhu Goodbye,cruelworld 7、編程注意事項

27、1; License問題。Linux內(nèi)核源碼以GPL許可發(fā)布,模塊如果不聲明自己使 用的license,加載的時候警告??梢允褂?MODULE_LICENSEGPL )來 避免。避免“名字空間污染”:因為模塊動態(tài)鏈接到內(nèi)核里,最好不要輸出內(nèi)核 中已有的全局函數(shù)或全局變量。否則會后者會影響前者??梢酝ㄟ^查看 /proc/kallsyms 來查看內(nèi)核符號列表。解決方法:o export_no_symbOLS此宏,這個模塊不輸出任何符號,除了使 用下面的宏定義的符號。o EXPORT_SYMBOL( nam使用此宏定義的符號,強制輸出。需要在 EXPORT_NO_SYMB使LS之前使用才能輸出??梢?/p>

28、輸出 static 的 符號。模塊之間的依賴問題:有的模塊依賴于其他模塊的函數(shù)或者變量, 在加載 前需要先加載所依賴的所有模塊后,才能成功加載。卸載模塊時要先卸載 被依賴的所有模塊后,才能成功卸載。8、集成模塊到內(nèi)核步驟*使用modulenit和module_exit宏來定義內(nèi)核模塊接口函數(shù),并確保模 塊工作正常(hello.c )*把模塊文件hello.c 拷貝到內(nèi)核的選定目錄(例如:drivers/char 目錄)* 修改選定目錄(例如:drivers/char 目錄)下的Kconfig文件和Makefile 文件o 修改Kconfig文件,增加如下:con figHELLOtristat

29、e'NewHello'o 修改Makefile 文件,增加如下:obj-$(CONFIG_HELLO)+=hello.o*重新配置內(nèi)核,選中要將該功能編譯進內(nèi)核,而不是編譯為模塊。重新編譯內(nèi)核,如果成功,則得到新內(nèi)核。測試此內(nèi)核,確保內(nèi)核模塊已集成。八、查看系統(tǒng)支持的設(shè)備* /proc/devices :系統(tǒng)支持的字符設(shè)備驅(qū)動和塊設(shè)備驅(qū)動,及其對應(yīng)的主 設(shè)備號。o #cat/proc/devicesCharacterdevices:1mem10misc29fb400leds232butt onsBlockdevices:1ramdisk31mtdblock254sbull* d

30、mesg查看系統(tǒng)的啟動信息??梢钥吹较到y(tǒng)支持的驅(qū)動的一些打印信息o #dmesgleds in itializedsnu ll:s nu lli nitializedbutt onsin itializedsnu ll:e nters nu ll_ope n* /proc/ioports(/proc/iomem) :查看設(shè)備的IO內(nèi)存物理地址。o #cat/proc/iomem19000300-19000310:cs890019000300-19000310:cs890030000000-33ffffff:SystemRAM30024000-30293fff:Kerneltext30294000-302f1f97:Kerneldata49000000-490fffff:s3c2410-ohci49000000-490fffff:ohci_hcd4d000000-4d0fffff:s3c2410-lcd4e000000-4e0fffff:s3c2440-nand4e000000-4e0fffff:s3c2440-nand50000000-50003fff:s3c2440-uart.050000000-500000ff:s3c2440-uart50

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論