Linux系統(tǒng)驅(qū)動(dòng)概述.ppt
《Linux系統(tǒng)驅(qū)動(dòng)概述.ppt》由會(huì)員分享,可在線閱讀,更多相關(guān)《Linux系統(tǒng)驅(qū)動(dòng)概述.ppt(34頁珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
Linux系統(tǒng)驅(qū)動(dòng)概述,驅(qū)動(dòng)程序與應(yīng)用程序的區(qū)別,應(yīng)用程序一般有一個(gè)main函數(shù),從頭到尾執(zhí)行一個(gè)任務(wù);應(yīng)用程序可以和GLIBC庫(kù)連接驅(qū)動(dòng)程序沒有main函數(shù),通過使用宏module_init(初始化函數(shù)名)將初始化函數(shù)加入內(nèi)核全局初始化函數(shù)列表中,在內(nèi)核初始化時(shí)執(zhí)行驅(qū)動(dòng)的初始化函數(shù),從而完成驅(qū)動(dòng)的初始化和注冊(cè),之后驅(qū)動(dòng)便停止等待被應(yīng)用軟件調(diào)用。驅(qū)動(dòng)程序中有一個(gè)宏moudule_exit(退出處理函數(shù)名)注冊(cè)退出處理函數(shù)。它在驅(qū)動(dòng)退出時(shí)被調(diào)用。驅(qū)動(dòng)程序中是不能使用標(biāo)準(zhǔn)C庫(kù)的,內(nèi)核版本與編譯器的版本依賴,當(dāng)模塊與內(nèi)核鏈接時(shí),insmod會(huì)檢查模塊和當(dāng)前內(nèi)核版本是否匹配,每個(gè)模塊都定義了版本符號(hào)__module_kernel_version,這個(gè)符號(hào)位于模塊文件的ELF頭的.modinfo段中。只要在模塊中包含,編譯器就會(huì)自動(dòng)定義這個(gè)符號(hào)每個(gè)內(nèi)核版本都需要特定版本的編譯器的支持,高版本的編譯器并不適合低版本的內(nèi)核,Linux-2.4版本的insmod命令裝載模塊時(shí),首先從/lib/modules目錄和內(nèi)核相關(guān)的子目錄中查找模塊文件,如果需要從當(dāng)前目錄裝載,使用insmodmodule.o。,設(shè)備驅(qū)動(dòng)程序的作用,設(shè)備驅(qū)動(dòng)程序?qū)?fù)雜的硬件抽象成一個(gè)結(jié)構(gòu)良好的設(shè)備,并通過提供統(tǒng)一的程序接口為系統(tǒng)的其它部分提供使用設(shè)備的能力和方法。設(shè)備驅(qū)動(dòng)程序(應(yīng)該只是)為系統(tǒng)的其它部分提供各種使用設(shè)備的能力,使用設(shè)備的方法應(yīng)該由應(yīng)用程序決定。Linux下對(duì)外設(shè)的訪問只能通過驅(qū)動(dòng)程序Linux對(duì)于驅(qū)動(dòng)程序有統(tǒng)一的接口,以文件的形式定義系統(tǒng)的驅(qū)動(dòng)程序:Open、Release、read、write、ioctl…驅(qū)動(dòng)程序是內(nèi)核的一部分,可以使用中斷、DMA等操作驅(qū)動(dòng)程序需要在用戶態(tài)和內(nèi)核態(tài)之間傳遞數(shù)據(jù),設(shè)備驅(qū)動(dòng)程序的分類,字符設(shè)備驅(qū)動(dòng)程序各種串行接口,并行接口等。塊設(shè)備驅(qū)動(dòng)程序磁盤設(shè)備等網(wǎng)絡(luò)設(shè)備驅(qū)動(dòng)程序網(wǎng)卡等。雜項(xiàng)設(shè)備驅(qū)動(dòng)程序不屬于上述三種設(shè)備之外的一些設(shè)備,如SCSI,時(shí)鐘等。,在操作系統(tǒng)中的位置,設(shè)備驅(qū)動(dòng)程序是內(nèi)核代碼的一部分。驅(qū)動(dòng)程序的地址空間是內(nèi)核的地址空間。驅(qū)動(dòng)程序的代碼直接對(duì)設(shè)備硬件(實(shí)際是設(shè)備的各種寄存器)進(jìn)行控制(實(shí)際就是讀寫操作)。應(yīng)用程序通過操作系統(tǒng)的系統(tǒng)調(diào)用執(zhí)行相應(yīng)的驅(qū)動(dòng)程序函數(shù)。中斷則直接執(zhí)行相應(yīng)的中斷程序代碼。設(shè)備驅(qū)動(dòng)程序的file_operations結(jié)構(gòu)體的地址被注冊(cè)到內(nèi)核中的設(shè)備鏈表中。塊設(shè)備和字符設(shè)備以設(shè)備文件的方式建立在文件系統(tǒng)中的/dev目錄下,而且每個(gè)設(shè)備都有一個(gè)主設(shè)備號(hào)和一個(gè)次設(shè)備號(hào)。,在操作系統(tǒng)中的位置,主設(shè)備號(hào)和次設(shè)備號(hào),主設(shè)備號(hào)相同的設(shè)備使用相同的驅(qū)動(dòng)程序,次設(shè)備號(hào)用于區(qū)分具體設(shè)備的實(shí)例。主設(shè)備號(hào)標(biāo)識(shí)設(shè)備對(duì)應(yīng)的驅(qū)動(dòng)程序一個(gè)驅(qū)動(dòng)程序可以控制若干個(gè)設(shè)備,次設(shè)備號(hào)提供了一種區(qū)分它們的方法系統(tǒng)增加一個(gè)驅(qū)動(dòng)程序就要賦予它一個(gè)主設(shè)備號(hào)。這一賦值過程在驅(qū)動(dòng)程序的初始化過程中intregister_chrdev(unsignedintmajor,constchar*name,structfile_operations*fops);,主設(shè)備號(hào)和次設(shè)備號(hào),創(chuàng)建設(shè)備節(jié)點(diǎn),設(shè)備已經(jīng)注冊(cè)到內(nèi)核表中,對(duì)于設(shè)備的訪問通過設(shè)備文件(設(shè)備文件與設(shè)備驅(qū)動(dòng)程序的主設(shè)備號(hào)匹配),內(nèi)核會(huì)調(diào)用驅(qū)動(dòng)程序中的正確函數(shù)給程序一個(gè)它們可以請(qǐng)求設(shè)備驅(qū)動(dòng)程序的名字。這個(gè)名字必須插入到/dev目錄中,并與驅(qū)動(dòng)程序的主設(shè)備號(hào)和次設(shè)備號(hào)相連使用mknod在文件系統(tǒng)上創(chuàng)建一個(gè)設(shè)備節(jié)點(diǎn)mknod/dev/mydevicec2540,動(dòng)態(tài)分配設(shè)備號(hào),在Documentation/device.txt文件中可以找到已經(jīng)靜態(tài)分配給大部分設(shè)備的列表由于許多數(shù)字已經(jīng)分配了,為新設(shè)備選擇一個(gè)唯一的號(hào)碼是很困難的如果調(diào)用register_chrdev時(shí)的major為零,函數(shù)就會(huì)選擇一個(gè)空閑號(hào)碼并做為返回值返回,動(dòng)態(tài)分配的問題,動(dòng)態(tài)分配的主設(shè)備號(hào)不能保證總是一樣的,無法事先創(chuàng)建設(shè)備節(jié)點(diǎn)可以從/proc/devices讀取cat/proc/devices利用腳本動(dòng)態(tài)創(chuàng)建設(shè)備文件節(jié)點(diǎn),設(shè)備管理的問題,如今,Linux支持很多不同種類的硬件。這意味著/dev中都有數(shù)百個(gè)特殊文件來表示所有這些設(shè)備。而且,這些特殊文件中大多數(shù)甚至不會(huì)映射到系統(tǒng)中存在的設(shè)備上,使用devfs,在Linux2.4的內(nèi)核里引入了devfs來解決linux下設(shè)備文件管理的問題在驅(qū)動(dòng)程序中通過devfs_register()函數(shù)創(chuàng)建設(shè)備文件系統(tǒng)的節(jié)點(diǎn)系統(tǒng)啟動(dòng)的時(shí)候mount設(shè)備文件系統(tǒng)所有需要的設(shè)備節(jié)點(diǎn)都由內(nèi)核自動(dòng)管理。/dev目錄下只有掛載的設(shè)備,Linux2.6內(nèi)核與devfs,Linux2.6內(nèi)核引入了sysfs文件系統(tǒng)為每個(gè)系統(tǒng)的硬件樹進(jìn)行分級(jí)處理Devfs在Linux2.6中被標(biāo)記為舍棄的特性(在Linux2.6.15及以后的版本則取消了對(duì)它的支持),而使用udev。維護(hù)動(dòng)態(tài)設(shè)備從sysfs獲得的信息,可以提供對(duì)特定設(shè)備的固定設(shè)備名。對(duì)于熱插拔的設(shè)備,這尤其重要udev是在用戶空間的腳本文件,這很容易被編輯和修改可以和hotplug腳本配合使用為了保證舊應(yīng)用程序的兼容性,在嵌入式系統(tǒng)中,用devfs還是一個(gè)好方法。即使在Linux2.6.15內(nèi)核以后,也可以通過ndevfs(nanodevfs)補(bǔ)丁提供對(duì)devfs特性的兼容。,在Linux2.6內(nèi)核中使用udev,建議,在2.6.15以后的版本中使用udev使用ramfs作為udev的載體mount–tramfsnone/devudev使用的規(guī)則集位于/etc/udev/*udev的官方地址:http://www.kernel.org/pub/linux/utils/kernel/hotplug/udev.html,設(shè)備驅(qū)動(dòng)程序的使用方法,應(yīng)用層使用open、close、read、write系統(tǒng)調(diào)用——需要編寫應(yīng)用程序使用系統(tǒng)命令可以進(jìn)行最基本的測(cè)試:cat/dev/urandomecho/dev/urandom>/dev/fb0ddif=/dev/touchscreenof=/var/tmp/testbs=16count=100,Linux設(shè)備驅(qū)動(dòng)程序結(jié)構(gòu),結(jié)構(gòu)體file_operations的定義,在include/linux/fs.h中主要包括:open,close(或者release),read,write,ioctl,poll,mmap等,簡(jiǎn)單的Linux驅(qū)動(dòng)程序原理,,Linux設(shè)備驅(qū)動(dòng)程序結(jié)構(gòu)的例子(1),Linux設(shè)備驅(qū)動(dòng)程序結(jié)構(gòu)的例子(2),/**驅(qū)動(dòng)程序中使用的各種函數(shù)的原型聲明。標(biāo)準(zhǔn)的作法是將函數(shù)原型聲明*放在一個(gè)頭文件中,然后在該文件開始處使用#include引用,并在該*文件中定義。**這里我們將函數(shù)的聲明和定義放在一起。所以下面的代碼既是函數(shù)的聲明,*也是函數(shù)的定義。*/staticssize_tdemo_read(structfile*filp,char*buffsize_tcnt,loof_t*off){/*這里是read函數(shù)的代碼*/returnret;}staticssize_tdemo_write(structfile*filp,char*buffsize_tcnt,loff_t*off){/*這里是write函數(shù)的代碼*/returnret;},Linux設(shè)備驅(qū)動(dòng)程序結(jié)構(gòu)的例子(3),staticintdemo_ioctl(structinode*inode,structfile*filpunsignedintcmd,unsignedlongarg){/*這里是ioctl函數(shù)的代碼,它的一般格式為一個(gè)switch分支語句*switch(cmd){*caseCMD1:*...*break;*...*caseCMDn:*...*break*default:*...*break;*}*/returnret;}ioctl()函數(shù)用于控制驅(qū)動(dòng)程序本身的一些特性和參數(shù),如設(shè)定驅(qū)動(dòng)程序使用的緩沖區(qū)的大小,設(shè)定串行通訊的速率等。,Linux設(shè)備驅(qū)動(dòng)程序結(jié)構(gòu)的例子(4),staticintdemo_open(structinode*inode,structfile*filp){/*這里是open函數(shù)的代碼*/returnret;}staticintdemo_close(structinode*inode,structfile*filp){/*這里是close函數(shù)的代碼*/returnret;},上述5個(gè)函數(shù),既read(),write(),ioctl(),open(),close(),是一個(gè)字符設(shè)備驅(qū)動(dòng)程序最基本的需要由驅(qū)動(dòng)程序的作者完成的函數(shù)。這5個(gè)函數(shù)將對(duì)應(yīng)于相應(yīng)的5個(gè)系統(tǒng)調(diào)用:,Linux設(shè)備驅(qū)動(dòng)程序結(jié)構(gòu)的例子(5),staticstructfile_operationsdemo_fops={read:demo_read,write:demo_write,ioctl:demo_ioctl,open:demo_open,release:demo_close,};,file_operations是一個(gè)結(jié)構(gòu)體類型,定義在include/linux/fs.h中。上述代碼定義了一個(gè)file_operations類型的結(jié)構(gòu)體demo_fops,并將其中的一些成員賦了初值。結(jié)構(gòu)體demo_fops將作為一個(gè)參數(shù)在注冊(cè)一個(gè)設(shè)備驅(qū)動(dòng)程序時(shí)傳遞給內(nèi)核。內(nèi)核使用設(shè)備鏈表維護(hù)各種注冊(cè)的設(shè)備。不同類型的設(shè)備使用不同的鏈表。,Linux設(shè)備驅(qū)動(dòng)程序結(jié)構(gòu)的例子(6),staticint__initdemo_init(void){/*設(shè)備初始化代碼等*/if(register_chrdev(DEMO_MAJOR,“demo”,},Linux設(shè)備驅(qū)動(dòng)程序結(jié)構(gòu)的例子(7),module_init(demo_init);module_exit(demo_exit);這兩個(gè)函數(shù),module_init()和module_exit(),用于告訴內(nèi)核,當(dāng)一個(gè)驅(qū)動(dòng)程序加載和退出(或撤消)時(shí),需要執(zhí)行的操作。不同驅(qū)動(dòng)程序在加載和退出時(shí),除了基本的向內(nèi)核注冊(cè)設(shè)備驅(qū)動(dòng)程序外,還有各自的針對(duì)具體設(shè)備的操作。,Linux設(shè)備驅(qū)動(dòng)程序結(jié)構(gòu)的例子(8),要點(diǎn)總結(jié):宏:__KERNEL__,MODULE,__VERSION____KERNEL__:表明這將是用于內(nèi)核的代碼,否則很多內(nèi)核過程將無法使用。MODULE:如果是以模塊方式編譯,需要定義這個(gè)宏;如果是靜態(tài)連接則不用。__VERSION__:定義這個(gè)宏則需要驅(qū)動(dòng)程序的內(nèi)核版本要和內(nèi)核版本一致。module_init()/module_exit():[demo_init()/demo_exit()]每個(gè)驅(qū)動(dòng)程序都要有這兩個(gè)函數(shù),它們分別用于設(shè)備驅(qū)動(dòng)程序的加載和撤消。staticstructfile_operationsdemo_fops:每個(gè)驅(qū)動(dòng)程序都要有這樣的結(jié)構(gòu)體,可能不止一個(gè)。用register_chrdev()注冊(cè)驅(qū)動(dòng)程序時(shí)這個(gè)結(jié)構(gòu)體的起始地址被傳送到內(nèi)核的設(shè)備表中。DEMO_MAJOR:每個(gè)設(shè)備驅(qū)動(dòng)程序有一個(gè)主設(shè)備號(hào)(majornumber)。不同設(shè)備驅(qū)動(dòng)程序不能使用相同的主設(shè)備號(hào)。一個(gè)設(shè)備驅(qū)動(dòng)程序可以管理不同的(但一般是同一類的)設(shè)備,通過次設(shè)備號(hào)(minornumber)區(qū)分。demo_open()/close(),read()/write(),ioctl():根據(jù)具體驅(qū)動(dòng)程序定義和使用。一般open()/close()總是需要的,而且open()和close()一定要成對(duì)出現(xiàn)。,設(shè)備驅(qū)動(dòng)程序的使用,驅(qū)動(dòng)程序模塊的動(dòng)態(tài)鏈接和靜態(tài)鏈接創(chuàng)建設(shè)備文件使用設(shè)備,驅(qū)動(dòng)程序模塊的加載,設(shè)備驅(qū)動(dòng)程序被靜態(tài)編譯到內(nèi)核中的情況:module_init()指示內(nèi)核在啟動(dòng)過程中運(yùn)行設(shè)備的初始化函數(shù),如demo_init()函數(shù)。驅(qū)動(dòng)程序的加載隨內(nèi)核的啟動(dòng)一起完成。靜態(tài)編譯的內(nèi)核模塊不能被動(dòng)態(tài)卸載,只有到系統(tǒng)關(guān)閉時(shí)由內(nèi)核執(zhí)行相應(yīng)的卸載函數(shù),如demo_exit()。嵌入式操作系統(tǒng)一般使用靜態(tài)內(nèi)核模塊以減少系統(tǒng)的尺寸和復(fù)雜性。設(shè)備驅(qū)動(dòng)程序被動(dòng)態(tài)加載到內(nèi)核中的情況:首先,驅(qū)動(dòng)程序需要被編譯成目標(biāo)文件,如demo.o。在操作系統(tǒng)運(yùn)行之后,使用insmod命令將驅(qū)動(dòng)程序模塊動(dòng)態(tài)加載到內(nèi)核中$insmoddemo.o使用insmod命令動(dòng)態(tài)加載的內(nèi)核模塊可以使用rmmod命令動(dòng)態(tài)地從內(nèi)核中卸載$rmmoddemo.o使用內(nèi)核的動(dòng)態(tài)模塊加載/卸載功能需要內(nèi)核支持kmod功能。,創(chuàng)建設(shè)備文件,使用設(shè)備驅(qū)動(dòng),應(yīng)用程序??系統(tǒng)調(diào)用??設(shè)備驅(qū)動(dòng)程序??設(shè)備(寄存器)使用一個(gè)設(shè)備一般需要執(zhí)行如下一些操作:1.打開設(shè)備文件。2.對(duì)設(shè)備進(jìn)行必要的設(shè)置,如設(shè)置串口速率。3.對(duì)設(shè)備進(jìn)行讀、寫等操作,如通過串口收發(fā)數(shù)據(jù)。4.結(jié)束對(duì)設(shè)備的使用之前,如果改變了設(shè)備的某些設(shè)置,則將其恢復(fù)到缺省狀態(tài),保證設(shè)備停用后沒有任何不好的副作用。5.關(guān)閉設(shè)備。,,,,使用設(shè)備驅(qū)動(dòng),Linux的驅(qū)動(dòng)開發(fā)調(diào)試有兩種方法,直接編譯到內(nèi)核,再運(yùn)行新的內(nèi)核來測(cè)試。效率較低,但在某些場(chǎng)合是唯一的方法編譯為模塊的形式,單獨(dú)加載運(yùn)行調(diào)試。模塊方式調(diào)試效率很高,它使用insmod工具將編譯的模塊直接插入內(nèi)核,如果出現(xiàn)故障,可以使用rmmod從內(nèi)核中卸載模塊。不需要重新啟動(dòng)內(nèi)核,這使驅(qū)動(dòng)調(diào)試效率大大提高。,模塊方式驅(qū)動(dòng)程序編譯的兩種方法,在內(nèi)核中編譯。“參考內(nèi)核的移植和編譯.ppt中”的一個(gè)demo驅(qū)動(dòng)程序編譯的例子獨(dú)立編譯。在驅(qū)動(dòng)源代碼目錄下編寫makefile鏈接內(nèi)核源代碼,將它編譯為模塊。,- 1.請(qǐng)仔細(xì)閱讀文檔,確保文檔完整性,對(duì)于不預(yù)覽、不比對(duì)內(nèi)容而直接下載帶來的問題本站不予受理。
- 2.下載的文檔,不會(huì)出現(xiàn)我們的網(wǎng)址水印。
- 3、該文檔所得收入(下載+內(nèi)容+預(yù)覽)歸上傳者、原創(chuàng)作者;如果您是本文檔原作者,請(qǐng)點(diǎn)此認(rèn)領(lǐng)!既往收益都?xì)w您。
下載文檔到電腦,查找使用更方便
9.9 積分
下載 |
- 配套講稿:
如PPT文件的首頁顯示word圖標(biāo),表示該P(yáng)PT已包含配套word講稿。雙擊word圖標(biāo)可打開word文檔。
- 特殊限制:
部分文檔作品中含有的國(guó)旗、國(guó)徽等圖片,僅作為作品整體效果示例展示,禁止商用。設(shè)計(jì)者僅對(duì)作品中獨(dú)創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- Linux 系統(tǒng) 驅(qū)動(dòng) 概述
鏈接地址:http://zhongcaozhi.com.cn/p-3343896.html