第5章+嵌入式系統(tǒng)驅(qū)動(dòng)程序開(kāi)發(fā)_第1頁(yè)
第5章+嵌入式系統(tǒng)驅(qū)動(dòng)程序開(kāi)發(fā)_第2頁(yè)
第5章+嵌入式系統(tǒng)驅(qū)動(dòng)程序開(kāi)發(fā)_第3頁(yè)
第5章+嵌入式系統(tǒng)驅(qū)動(dòng)程序開(kāi)發(fā)_第4頁(yè)
第5章+嵌入式系統(tǒng)驅(qū)動(dòng)程序開(kāi)發(fā)_第5頁(yè)
已閱讀5頁(yè),還剩81頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、1第第5章章 嵌入式系統(tǒng)驅(qū)動(dòng)程序開(kāi)發(fā)嵌入式系統(tǒng)驅(qū)動(dòng)程序開(kāi)發(fā) 2主要內(nèi)容v模塊編程模塊編程v編譯模塊進(jìn)內(nèi)核編譯模塊進(jìn)內(nèi)核v嵌入式系統(tǒng)驅(qū)動(dòng)程序概述嵌入式系統(tǒng)驅(qū)動(dòng)程序概述v嵌入式系統(tǒng)驅(qū)動(dòng)程序結(jié)構(gòu)嵌入式系統(tǒng)驅(qū)動(dòng)程序結(jié)構(gòu)vLED燈驅(qū)動(dòng)程序?qū)嵗裏趄?qū)動(dòng)程序?qū)嵗?模塊編程模塊編程v內(nèi)核模塊內(nèi)核模塊是是Linux內(nèi)核向外部提供的一個(gè)插口內(nèi)核向外部提供的一個(gè)插口,其全稱(chēng)為,其全稱(chēng)為動(dòng)態(tài)可動(dòng)態(tài)可加載內(nèi)核模塊加載內(nèi)核模塊(Loadable Kernel Module,LKM)。)。vLinux本身是一個(gè)本身是一個(gè)單內(nèi)核單內(nèi)核,單內(nèi)核的最大優(yōu)點(diǎn)是效率高,因?yàn)樗?,單?nèi)核的最大優(yōu)點(diǎn)是效率高,因?yàn)樗械膬?nèi)容都集成在一起,但其

2、缺點(diǎn)是可擴(kuò)展性和可維護(hù)性相對(duì)較有的內(nèi)容都集成在一起,但其缺點(diǎn)是可擴(kuò)展性和可維護(hù)性相對(duì)較差,模塊機(jī)制就是為了彌補(bǔ)這一缺陷。差,模塊機(jī)制就是為了彌補(bǔ)這一缺陷。4模塊編程模塊編程v模塊是具有獨(dú)立功能的程序,它可以被單獨(dú)編譯,但不能獨(dú)立運(yùn)模塊是具有獨(dú)立功能的程序,它可以被單獨(dú)編譯,但不能獨(dú)立運(yùn)行。行。v模塊在運(yùn)行時(shí)被鏈接到內(nèi)核作為內(nèi)核的一部分在內(nèi)核空間運(yùn)行,模塊在運(yùn)行時(shí)被鏈接到內(nèi)核作為內(nèi)核的一部分在內(nèi)核空間運(yùn)行,這與運(yùn)行在用戶(hù)空間的進(jìn)程是不同的。這與運(yùn)行在用戶(hù)空間的進(jìn)程是不同的。v模塊通常由一組函數(shù)和數(shù)據(jù)結(jié)構(gòu)組成,用來(lái)實(shí)現(xiàn)一種文件系統(tǒng)、模塊通常由一組函數(shù)和數(shù)據(jù)結(jié)構(gòu)組成,用來(lái)實(shí)現(xiàn)一種文件系統(tǒng)、一個(gè)驅(qū)動(dòng)程

3、序或其它內(nèi)核上層的功能。一個(gè)驅(qū)動(dòng)程序或其它內(nèi)核上層的功能。5v將模塊從內(nèi)核中獨(dú)立出來(lái),不必預(yù)先綁在將模塊從內(nèi)核中獨(dú)立出來(lái),不必預(yù)先綁在kernel codes 中。中。這樣做有這樣做有三種優(yōu)點(diǎn)三種優(yōu)點(diǎn): 1)將來(lái)修改內(nèi)核時(shí),不必全部重新編譯,可節(jié)省不少時(shí)間;)將來(lái)修改內(nèi)核時(shí),不必全部重新編譯,可節(jié)省不少時(shí)間;2) 若需要安裝新的模塊若需要安裝新的模塊 ,不必重新編譯內(nèi)核,不必重新編譯內(nèi)核 ,只要插入,只要插入(通過(guò)(通過(guò)insmode指令)指令) 對(duì)應(yīng)的模塊即可;對(duì)應(yīng)的模塊即可;3)減少內(nèi)核對(duì)系統(tǒng)資源的占用,內(nèi)核可以集中精力做最基本)減少內(nèi)核對(duì)系統(tǒng)資源的占用,內(nèi)核可以集中精力做最基本的事情,把

4、一些擴(kuò)展功能都交由模塊實(shí)現(xiàn)。的事情,把一些擴(kuò)展功能都交由模塊實(shí)現(xiàn)。6模塊編程模塊編程v模塊命令模塊命令insmod 掛載模塊掛載模塊vinsmod hello.ko 將將hello.ko模塊插入到內(nèi)核中模塊插入到內(nèi)核中rmmod 移除已掛載模塊移除已掛載模塊vrmmod hello.ko 將將hello.ko模塊從內(nèi)核中卸載模塊從內(nèi)核中卸載lsmod 列出已經(jīng)加載的內(nèi)核模塊列出已經(jīng)加載的內(nèi)核模塊modinfo 查看模塊信息查看模塊信息 vmodinfo hello.ko 查看查看hello.ko模塊信息模塊信息 modprobe 自動(dòng)根據(jù)依賴(lài)文件裝入模塊自動(dòng)根據(jù)依賴(lài)文件裝入模塊vdmesg查看

5、查看log信息信息7vmodprobev功能說(shuō)明:功能說(shuō)明:自動(dòng)處理可載入模塊自動(dòng)處理可載入模塊。v語(yǔ)法:語(yǔ)法:modprobe -acdlrtvV-help模塊文件模塊文件符號(hào)名稱(chēng)符號(hào)名稱(chēng) = 符號(hào)值符號(hào)值v補(bǔ)充說(shuō)明:補(bǔ)充說(shuō)明:modprobe可載入可載入指定的個(gè)別指定的個(gè)別模塊,或是載入模塊,或是載入一組相依的模塊一組相依的模塊。modprobe會(huì)根據(jù)會(huì)根據(jù)depmod所產(chǎn)生的相依關(guān)系,所產(chǎn)生的相依關(guān)系,決定要載入哪些模決定要載入哪些模塊塊。若在載入過(guò)程中若在載入過(guò)程中發(fā)生錯(cuò)誤發(fā)生錯(cuò)誤,在,在modprobe會(huì)卸載整組的模塊會(huì)卸載整組的模塊。8vmodprobe v參數(shù):參數(shù): -a或或-

6、all 載入全部的模塊。載入全部的模塊。 -c或或-show-conf 顯示所有模塊的設(shè)置信息。顯示所有模塊的設(shè)置信息。 -d或或-debug 使用排錯(cuò)模式。使用排錯(cuò)模式。 -k或或-autoclean 指定模塊設(shè)置為指定模塊設(shè)置為自動(dòng)清除自動(dòng)清除模式。模式。 -l或或-list 顯示可用的模塊。顯示可用的模塊。 -n或或- show 僅僅顯示要執(zhí)行的操作僅僅顯示要執(zhí)行的操作,而不實(shí)際執(zhí)行而不實(shí)際執(zhí)行 -q或或 -quiet 不顯示錯(cuò)誤信息。不顯示錯(cuò)誤信息。9vmodprobe v參數(shù):參數(shù): -r或或-remove 模塊閑置不用時(shí),即自動(dòng)卸載模塊。模塊閑置不用時(shí),即自動(dòng)卸載模塊。 -s或或-

7、syslog /將結(jié)果記錄到系統(tǒng)記錄中將結(jié)果記錄到系統(tǒng)記錄中 。 -t或或-type 指定模塊類(lèi)型。指定模塊類(lèi)型。 -v或或-verbose 執(zhí)行時(shí)顯示詳細(xì)的信息。執(zhí)行時(shí)顯示詳細(xì)的信息。 -V或或-version 顯示版本信息。顯示版本信息。 -C或或-config configfile 指定配置文件,默認(rèn)使用指定配置文件,默認(rèn)使用 /etc/modules.conf文件為配置文件。文件為配置文件。 -h或或-help 顯示幫助。顯示幫助。 10vinsmod 掛載模塊掛載模塊insmod這個(gè)工具,和這個(gè)工具,和modprobe有點(diǎn)類(lèi)似,但功能上沒(méi)有有點(diǎn)類(lèi)似,但功能上沒(méi)有modprobe強(qiáng),強(qiáng)

8、,modprobe在掛載模塊是在掛載模塊是不用指定模塊文件的路徑不用指定模塊文件的路徑,也,也不用帶不用帶文件的后綴文件的后綴.o 或或.ko ;而而insmod 需要的是模塊的所在目錄的絕對(duì)路徑,并且一定要需要的是模塊的所在目錄的絕對(duì)路徑,并且一定要帶有模塊文件名后綴的帶有模塊文件名后綴的(modulefile.o 或或modulesfile.ko )11模塊編程模塊編程v一個(gè)一個(gè)linux內(nèi)核模塊主要由以下幾個(gè)部分組成內(nèi)核模塊主要由以下幾個(gè)部分組成 模塊加載函數(shù)模塊加載函數(shù)(必須必須)模塊卸載函數(shù)模塊卸載函數(shù)(必須必須)模塊許可證聲明模塊許可證聲明(必須必須)模塊參數(shù)模塊參數(shù)(可選可選)模

9、塊導(dǎo)出符號(hào)模塊導(dǎo)出符號(hào)(可選可選)模塊作者等信息聲明模塊作者等信息聲明 (可選可選) 12模塊編程模塊編程v模塊加載函數(shù)模塊加載函數(shù)當(dāng)通過(guò)當(dāng)通過(guò)insmod命令加載內(nèi)核模塊時(shí),模塊的加載函數(shù)會(huì)自動(dòng)被內(nèi)核命令加載內(nèi)核模塊時(shí),模塊的加載函數(shù)會(huì)自動(dòng)被內(nèi)核執(zhí)行,完成本模塊的相關(guān)初始化工作。執(zhí)行,完成本模塊的相關(guān)初始化工作。 linux模塊加載函數(shù)的形式如下模塊加載函數(shù)的形式如下:static int initialization_function(void) /*初始化代碼初始化代碼*/ 模塊加載函數(shù)必須以模塊加載函數(shù)必須以module_init(initialization_function)的形式

10、被的形式被指定。它返回整型值,若初始化成功,返回指定。它返回整型值,若初始化成功,返回0,否則返回錯(cuò)誤編碼。,否則返回錯(cuò)誤編碼。當(dāng)通過(guò)當(dāng)通過(guò)insmod和和modprobe命令加載內(nèi)核模塊時(shí),模塊的加載函數(shù)命令加載內(nèi)核模塊時(shí),模塊的加載函數(shù)會(huì)自動(dòng)被內(nèi)核執(zhí)行,完成本模塊的相關(guān)初始化工作。會(huì)自動(dòng)被內(nèi)核執(zhí)行,完成本模塊的相關(guān)初始化工作。 13模塊編程模塊編程v模塊卸載函數(shù)模塊卸載函數(shù)當(dāng)通過(guò)當(dāng)通過(guò)rmmod命令卸載內(nèi)核模塊時(shí),模塊的卸載函數(shù)會(huì)自動(dòng)被內(nèi)核執(zhí)命令卸載內(nèi)核模塊時(shí),模塊的卸載函數(shù)會(huì)自動(dòng)被內(nèi)核執(zhí)行,完成與模塊加載函數(shù)相反的功能。行,完成與模塊加載函數(shù)相反的功能。 linux內(nèi)核模塊卸載函數(shù)的形式

11、如下內(nèi)核模塊卸載函數(shù)的形式如下:static void cleanup_function(void) /*釋放代碼釋放代碼*/ 模塊卸載函數(shù)在模塊卸載的時(shí)候執(zhí)行,不返回任何值,必須以模塊卸載函數(shù)在模塊卸載的時(shí)候執(zhí)行,不返回任何值,必須以module_exit(cleanup_function)的形式來(lái)指定的形式來(lái)指定; 模塊卸載函數(shù)在模塊卸載的時(shí)候執(zhí)行,不返回任何值,必須以模塊卸載函數(shù)在模塊卸載的時(shí)候執(zhí)行,不返回任何值,必須以“module_exit(函數(shù)名函數(shù)名)”的形式來(lái)指定。的形式來(lái)指定。14模塊編程模塊編程v通常來(lái)說(shuō),模塊卸載函數(shù)要完成與模塊加載函數(shù)相反的功能:通常來(lái)說(shuō),模塊卸載函數(shù)要

12、完成與模塊加載函數(shù)相反的功能:若模塊加載函數(shù)注冊(cè)了若模塊加載函數(shù)注冊(cè)了XXX,則模塊卸載函數(shù)應(yīng)該注銷(xiāo),則模塊卸載函數(shù)應(yīng)該注銷(xiāo)XXX;若模塊記載函數(shù)的動(dòng)態(tài)申請(qǐng)了內(nèi)存,則模塊函數(shù)應(yīng)該釋放該該若模塊記載函數(shù)的動(dòng)態(tài)申請(qǐng)了內(nèi)存,則模塊函數(shù)應(yīng)該釋放該該內(nèi)存。內(nèi)存。若模塊加載函數(shù)申請(qǐng)了硬件資源若模塊加載函數(shù)申請(qǐng)了硬件資源(中斷,中斷,DMA通道、通道、I/O端口和端口和I/O內(nèi)存等內(nèi)存等)的占用,則模塊卸載函數(shù)應(yīng)該釋放這些硬件資源。的占用,則模塊卸載函數(shù)應(yīng)該釋放這些硬件資源。模塊加載函數(shù)一般用來(lái)開(kāi)啟硬件,模塊卸載函數(shù)一般要關(guān)閉硬模塊加載函數(shù)一般用來(lái)開(kāi)啟硬件,模塊卸載函數(shù)一般要關(guān)閉硬件。件。15模塊編程模塊編

13、程v模塊許可證聲明模塊許可證聲明MODULE_LICENSE(Daul BSD/GPL)模塊許可證模塊許可證(LICENSE)聲明聲明描述內(nèi)核模塊的許可權(quán)限描述內(nèi)核模塊的許可權(quán)限,如果不聲,如果不聲明明LICENSE,模塊被加載時(shí),將收到內(nèi)核被污染,模塊被加載時(shí),將收到內(nèi)核被污染(kernel tainted)的警告。的警告。 在在linux2.6內(nèi)核中,可接受的內(nèi)核中,可接受的LICENSE包括包括“GPL”、“GPL v2”、“GPL and additional rights”、“Dual BSD/GPL”、“Dual MPL/GPL”和和“Proprietary“。 大多數(shù)情況下,內(nèi)核

14、模塊應(yīng)遵循大多數(shù)情況下,內(nèi)核模塊應(yīng)遵循GPL兼容許可權(quán)。兼容許可權(quán)。linux2.6內(nèi)核內(nèi)核模塊中最常見(jiàn)的是以模塊中最常見(jiàn)的是以MODULE_LICENSE(“Dual BSD/GPL”)語(yǔ)語(yǔ)句聲明模塊采用句聲明模塊采用BSD/GPL雙雙LICENSE。16模塊編程模塊編程v模塊導(dǎo)出符號(hào)模塊導(dǎo)出符號(hào)Linux2.6的的“/proc/kallsyms”文件對(duì)應(yīng)著內(nèi)核符號(hào)表,它記錄了符文件對(duì)應(yīng)著內(nèi)核符號(hào)表,它記錄了符號(hào)以及符號(hào)所在的內(nèi)存地址。號(hào)以及符號(hào)所在的內(nèi)存地址。 內(nèi)核模塊可以使用如下宏導(dǎo)出符號(hào)內(nèi)核模塊可以使用如下宏導(dǎo)出符號(hào)(symbol,對(duì)應(yīng)于函數(shù)或變,對(duì)應(yīng)于函數(shù)或變量量)到內(nèi)核符號(hào)表。到內(nèi)

15、核符號(hào)表。vEXPORT_SYMBOL(符號(hào)名符號(hào)名);vEXPORT_SYMBOL_GPL(符號(hào)名符號(hào)名); /只適用于包含只適用于包含GPL許可權(quán)許可權(quán)的模塊。的模塊。 導(dǎo)出的符號(hào)將可以被其它模塊使用,導(dǎo)出的符號(hào)將可以被其它模塊使用,使用前聲明使用前聲明一下即可以。一下即可以。 17模塊編程模塊編程v模塊作者等信息聲明模塊作者等信息聲明MODULE_AUTOR(作者信息作者信息); MODULE_DESCRIPTION(模塊描述信息模塊描述信息); MODULE_VERSION(版本信息版本信息); MODULE_ALIAS(別名信息別名信息);MODULE_DEVICE_TABLE(設(shè)備

16、表信息設(shè)備表信息);18模塊編程模塊編程v介紹介紹printk()printk是在內(nèi)核中運(yùn)行的向控制臺(tái)輸出顯示的函數(shù)。是在內(nèi)核中運(yùn)行的向控制臺(tái)輸出顯示的函數(shù)。 模塊運(yùn)行在內(nèi)核空間,不能依賴(lài)于標(biāo)準(zhǔn)模塊運(yùn)行在內(nèi)核空間,不能依賴(lài)于標(biāo)準(zhǔn)C庫(kù)的。庫(kù)的。標(biāo)準(zhǔn)標(biāo)準(zhǔn)C庫(kù)需要調(diào)用操作系統(tǒng)內(nèi)核提供的系統(tǒng)調(diào)用來(lái)完成打印庫(kù)需要調(diào)用操作系統(tǒng)內(nèi)核提供的系統(tǒng)調(diào)用來(lái)完成打印字符的工作。字符的工作。19printk有有8個(gè)級(jí)別,定義在個(gè)級(jí)別,定義在中:中:v#define KERN_EMERG “” /*緊急事件消息,系統(tǒng)崩潰之前提示,表示系統(tǒng)不可用緊急事件消息,系統(tǒng)崩潰之前提示,表示系統(tǒng)不可用*/v#define KERN_

17、ALERT “” /*報(bào)告消息,表示必須立即采取措施報(bào)告消息,表示必須立即采取措施*/v #define KERN_CRIT “” /*臨界條件,通常涉及嚴(yán)重的硬件或軟件操作失敗臨界條件,通常涉及嚴(yán)重的硬件或軟件操作失敗*/v #define KERN_ERR “” /*錯(cuò)誤條件,驅(qū)動(dòng)程序常用錯(cuò)誤條件,驅(qū)動(dòng)程序常用KERN_ERR來(lái)報(bào)告硬件的錯(cuò)誤來(lái)報(bào)告硬件的錯(cuò)誤*/20printk有有8個(gè)級(jí)別,定義在個(gè)級(jí)別,定義在中:中:v#define KERN_WARNING “” /*警告條件,對(duì)可能出現(xiàn)問(wèn)題的情況進(jìn)行警告警告條件,對(duì)可能出現(xiàn)問(wèn)題的情況進(jìn)行警告*/v#define KERN_NOTICE

18、 “” /*正常但又重要的條件,用于提醒正常但又重要的條件,用于提醒*/v #define KERN_INFO “” /*提示信息,如驅(qū)動(dòng)程序啟動(dòng)時(shí),打印硬件信息提示信息,如驅(qū)動(dòng)程序啟動(dòng)時(shí),打印硬件信息*/v#define KERN_DEBUG “” /*調(diào)試級(jí)別的消息調(diào)試級(jí)別的消息*/21模塊編程模塊編程v通過(guò)通過(guò)”insmod hello.ko”命令可以加載它,加載時(shí)輸命令可以加載它,加載時(shí)輸出出”hello world”。v通過(guò)通過(guò)”rmmod hello”命令可以卸載它,命令可以卸載它, 卸載時(shí)輸出卸載時(shí)輸出”hello module exit”,v查看輸出信息可通過(guò)查看輸出信息可通過(guò)

19、dmesg命令。命令。22v編寫(xiě)一個(gè)編寫(xiě)一個(gè)hello.c模塊:模塊:1)編寫(xiě)代碼:)編寫(xiě)代碼: #include #include /* Needed by all modules */MODULE_LICENSE(“Dual BSD/GPL”);static int hello_init (void) printk(KERN_INFO “Hello world entern” ); /*內(nèi)核中打印信息要用內(nèi)核中打印信息要用printk(), 用戶(hù)中用用戶(hù)中用printf()。printk()可定義輸出級(jí)別可定義輸出級(jí)別 */ return 0;static void hello_exit(

20、void) printk(KERN_INFO “Hello World exit n );module_init(hello_init); /*加載模塊。若成功,返回加載模塊。若成功,返回0。失敗時(shí),應(yīng)輸出錯(cuò)誤編碼。失敗時(shí),應(yīng)輸出錯(cuò)誤編碼*/module_exit(hello_exit); /卸載模塊,不返回任何值。卸載模塊,不返回任何值。MODULE_DESCRIPTION(“A simple Hello World Module”);MODULE_ALIAS(“a simplest module”);23v加載模塊失敗時(shí)應(yīng)輸出錯(cuò)誤編碼,在加載模塊失敗時(shí)應(yīng)輸出錯(cuò)誤編碼,在Linux內(nèi)核中,錯(cuò)

21、誤編碼是內(nèi)核中,錯(cuò)誤編碼是一個(gè)負(fù)值。在一個(gè)負(fù)值。在中定義,包含中定義,包含-ENODEV、-ENOMEM之類(lèi)的符號(hào)值。之類(lèi)的符號(hào)值。v在在2.6內(nèi)核中,可用內(nèi)核中,可用request_module(const char *fmt, ) 函數(shù)函數(shù)加載內(nèi)核模塊。加載內(nèi)核模塊。24模塊編程模塊編程v實(shí)例實(shí)例1-1:用命令在:用命令在X86下加載和卸載下加載和卸載hello模塊模塊在同一目錄下在同一目錄下編輯編輯 Makefile 文件。文件。v添加這一行:添加這一行: obj-m := hello.o 編譯模塊編譯模塊: v # make -C /lib/modules/2.6.32-21-gene

22、ric/build M=$(pwd) modulesv編譯產(chǎn)生編譯產(chǎn)生hello.ko目標(biāo)文件目標(biāo)文件加載加載hello命令:命令:v#sudo insmod ./hello.ko用用rmmod可以卸載模塊可以卸載模塊v#sudo rmmod hello通過(guò)通過(guò)lsmod命令命令可以獲得系統(tǒng)中加載的所有模塊以及模塊間的可以獲得系統(tǒng)中加載的所有模塊以及模塊間的依賴(lài)關(guān)系。依賴(lài)關(guān)系。用命令用命令dmesg 來(lái)查看來(lái)查看log信息。信息。25模塊編程模塊編程v實(shí)例實(shí)例1-1說(shuō)明說(shuō)明vobj-m := hello.o obj-m 表示要由表示要由hello.c文件編譯得到文件編譯得到hello.o,并作

23、為模塊編,并作為模塊編譯,譯,obj-y 表示要連接進(jìn)內(nèi)核,表示要連接進(jìn)內(nèi)核,obj-x表示不會(huì)被編譯表示不會(huì)被編譯v/lib/modules/2.6.32-21-generic/ 是內(nèi)核模塊的安裝路徑,就是編是內(nèi)核模塊的安裝路徑,就是編譯內(nèi)核的時(shí)候譯內(nèi)核的時(shí)候“make modules_install”在在/lib/modules/目錄下目錄下生成的系統(tǒng)源碼包;生成的系統(tǒng)源碼包;vM=后面的是指存放后面的是指存放hello.c和和Makefile所在的目錄。所在的目錄。 26模塊編程模塊編程v實(shí)例實(shí)例1-2:編譯:編譯arm版本的版本的hello模塊模塊#make clean 清理中間文件和

24、目標(biāo)文件。清理中間文件和目標(biāo)文件。編譯編譯arm下的模塊:下的模塊: # make -C ././workhome/ces-6410/uboot/htx-linux-2.6.24-yaffs2 M=$(pwd) modulesv其中其中././workhome/ces-6410/uboot/htx-linux-2.6.24-yaffs2 是是目標(biāo)板的目標(biāo)板的linux內(nèi)核源碼目錄。內(nèi)核源碼目錄。注:注:編譯過(guò)的編譯過(guò)的2.6.24的的arm內(nèi)核是目標(biāo)板的內(nèi)核,在編譯時(shí)只內(nèi)核是目標(biāo)板的內(nèi)核,在編譯時(shí)只能用這個(gè)內(nèi)核進(jìn)行編譯。能用這個(gè)內(nèi)核進(jìn)行編譯。加載模塊:加載模塊:v將目標(biāo)文件將目標(biāo)文件hello

25、.ko放到目標(biāo)板上的放到目標(biāo)板上的/lib/modules/2.6.24.2下,下,v再加載:再加載:#insmod hello.ko查看模塊用查看模塊用lsmod 命令;命令;用用rmmod命令卸載模塊:命令卸載模塊:v#rmmod hello27模塊編程模塊編程v模塊參數(shù)模塊參數(shù)模塊參數(shù)是模塊被加載的時(shí)候可以被傳遞給模塊的值,它本模塊參數(shù)是模塊被加載的時(shí)候可以被傳遞給模塊的值,它本身對(duì)應(yīng)模塊內(nèi)部的全局變量。身對(duì)應(yīng)模塊內(nèi)部的全局變量。可以使用可以使用“module_param(參數(shù)名參數(shù)名,參數(shù)類(lèi)型參數(shù)類(lèi)型,讀讀/寫(xiě)權(quán)限寫(xiě)權(quán)限)”為為模塊定義一個(gè)參數(shù)。模塊定義一個(gè)參數(shù)。28v模塊參數(shù)模塊參數(shù)

26、v例如:下列代碼定義了一個(gè)整型參數(shù)和一個(gè)字符指針參數(shù)。例如:下列代碼定義了一個(gè)整型參數(shù)和一個(gè)字符指針參數(shù)。 static char *book_name=linux設(shè)備驅(qū)動(dòng)設(shè)備驅(qū)動(dòng); static int num = 4000; module_param(num, int, S_IRUGO); module_param(book_name, charp, S_IRGUO); 在裝載內(nèi)核模塊時(shí),用戶(hù)可以向內(nèi)核模塊傳遞參數(shù),在裝載內(nèi)核模塊時(shí),用戶(hù)可以向內(nèi)核模塊傳遞參數(shù), 形式為形式為“sudo insmod/modprobe 模塊名模塊名(例如例如linux.ko) 參數(shù)名參數(shù)名=參數(shù)值參數(shù)值”,

27、如果不傳遞,參數(shù)將使用,如果不傳遞,參數(shù)將使用模塊內(nèi)定義的模塊內(nèi)定義的默認(rèn)值默認(rèn)值。29v程序:程序:hello_param.c#include /所有模塊都需要的頭文件所有模塊都需要的頭文件#include / init&exit相關(guān)宏相關(guān)宏MODULE_LICENSE(“Dual BSD/GPL); static char *book_name = “dissecting Linux Device Driver”;static int num = 4000;static int hello_init (void)printk(Hello module initn);return 0

28、;static void hello_exit (void)printk(Hello module exitn);module_init(hello_init);module_exit(hello_exit); module_param(num, int, S_IRUGO);module_param(book_name, charp, S_IRUGO);30模塊編程模塊編程vMakefile模塊的編寫(xiě)需要配置過(guò)的內(nèi)核源碼,編譯過(guò)程首先會(huì)到內(nèi)模塊的編寫(xiě)需要配置過(guò)的內(nèi)核源碼,編譯過(guò)程首先會(huì)到內(nèi)核源碼目錄下,讀取頂層核源碼目錄下,讀取頂層Makefile文件,然后再返回模塊文件,然后再返回模塊所在的

29、目錄進(jìn)行編譯。所在的目錄進(jìn)行編譯。31模塊編程模塊編程v實(shí)例實(shí)例2:復(fù)雜點(diǎn)的:復(fù)雜點(diǎn)的Makefile文件文件vMakefile內(nèi)容內(nèi)容 ifneq ($(KERNELRELEASE),) obj-m := hello.o else KDIR:=/lib/modules/$(shell uname -r)/build PWD:=$(shell pwd) all: $(MAKE) -C $(KDIR) M=$(PWD) endif clean: rm -f *.o *.ko *.mod.c .hello* v編譯:編譯:make32v實(shí)例實(shí)例2:復(fù)雜點(diǎn)的:復(fù)雜點(diǎn)的Makefile文件文件KERN

30、ELRELEASE是在內(nèi)核源碼的頂層是在內(nèi)核源碼的頂層Makefile中定義的中定義的一個(gè)變量,當(dāng)?shù)谝淮巫x取執(zhí)行此一個(gè)變量,當(dāng)?shù)谝淮巫x取執(zhí)行此makefile時(shí),沒(méi)有被定義,時(shí),沒(méi)有被定義,所以所以make將讀取執(zhí)行將讀取執(zhí)行else之后的內(nèi)容。之后的內(nèi)容。如果如果make的目標(biāo)是的目標(biāo)是clean,直接執(zhí)行,直接執(zhí)行clean操作,然后結(jié)束。操作,然后結(jié)束。如果如果make的目標(biāo)是的目標(biāo)是all,-C $(KDIR)指明跳轉(zhuǎn)到內(nèi)核源碼目錄指明跳轉(zhuǎn)到內(nèi)核源碼目錄下讀取那里的下讀取那里的makefile; M=$(PWD)表明返回到當(dāng)前目錄繼表明返回到當(dāng)前目錄繼續(xù)讀入,執(zhí)行當(dāng)前的續(xù)讀入,執(zhí)行當(dāng)前

31、的makefile。 33模塊編程模塊編程v模塊依賴(lài)于模塊依賴(lài)于Linux版本、版本、CPU等因素等因素v查看可以下載的查看可以下載的Linux內(nèi)核源碼包內(nèi)核源碼包sudo apt-cache search linux-sourcev選定要下載的源碼包選定要下載的源碼包sudo apt-get install linux-source-2.6.32下載完成后,在下載完成后,在/usr/src下,文件名為:下,文件名為:linux-source-2.6.32.tar.bz2 的壓縮包的壓縮包34編譯模塊進(jìn)內(nèi)核編譯模塊進(jìn)內(nèi)核v2.6內(nèi)核的源碼樹(shù)的目錄下一般內(nèi)核的源碼樹(shù)的目錄下一般都會(huì)有都會(huì)有兩個(gè)文

32、檔兩個(gè)文檔 Kconfig (2.4版版本是本是Config.in)和)和Makefile。v分布到各目錄的分布到各目錄的Kconfig構(gòu)成了一個(gè)構(gòu)成了一個(gè)分布式的內(nèi)核配置數(shù)據(jù)庫(kù)分布式的內(nèi)核配置數(shù)據(jù)庫(kù),每個(gè)每個(gè)Kconfig分別描述了分別描述了所屬目錄源文件相關(guān)的內(nèi)核配置菜單所屬目錄源文件相關(guān)的內(nèi)核配置菜單。在內(nèi)核配置在內(nèi)核配置make menuconfig(或(或xconfig等)時(shí),從等)時(shí),從Kconfig中讀出配置菜單,用戶(hù)配置完成后保存到中讀出配置菜單,用戶(hù)配置完成后保存到.config(在頂層目錄下(在頂層目錄下生成)中生成)中。在內(nèi)核編譯時(shí),主。在內(nèi)核編譯時(shí),主Makefile調(diào)

33、用這個(gè)調(diào)用這個(gè).config,就知道,就知道了用戶(hù)對(duì)內(nèi)核的配置情況。了用戶(hù)對(duì)內(nèi)核的配置情況。 35編譯模塊進(jìn)內(nèi)核編譯模塊進(jìn)內(nèi)核vKconfig對(duì)應(yīng)著對(duì)應(yīng)著內(nèi)核的配置菜單內(nèi)核的配置菜單,要想,要想添加新的驅(qū)動(dòng)添加新的驅(qū)動(dòng)到到內(nèi)核內(nèi)核的源碼中的源碼中,可以通過(guò),可以通過(guò)修改修改Kconfig來(lái)增加對(duì)我們驅(qū)動(dòng)的配置來(lái)增加對(duì)我們驅(qū)動(dòng)的配置菜單,這樣就有途徑選擇我們的驅(qū)動(dòng)。菜單,這樣就有途徑選擇我們的驅(qū)動(dòng)。v假如想使這個(gè)假如想使這個(gè)驅(qū)動(dòng)被編譯驅(qū)動(dòng)被編譯,還要,還要修改修改該驅(qū)動(dòng)所在目錄下的該驅(qū)動(dòng)所在目錄下的Makefile。v因此,一般添加新的驅(qū)動(dòng)時(shí)需要因此,一般添加新的驅(qū)動(dòng)時(shí)需要修改的文件有修改的文件

34、有兩種兩種(注意不(注意不只是兩個(gè))。只是兩個(gè))。 *Kconfig,*Makefile 要想知道怎么修改這兩種文件,就要知道這兩種文件的語(yǔ)法要想知道怎么修改這兩種文件,就要知道這兩種文件的語(yǔ)法結(jié)構(gòu)。結(jié)構(gòu)。36v(1)Kconfigv每個(gè)菜單項(xiàng)都有一個(gè)每個(gè)菜單項(xiàng)都有一個(gè)關(guān)鍵字標(biāo)識(shí)關(guān)鍵字標(biāo)識(shí),最常見(jiàn)的就是,最常見(jiàn)的就是config。v語(yǔ)法:語(yǔ)法:config symboloptionssymbol就是就是新的菜單項(xiàng)新的菜單項(xiàng),options是在這個(gè)新的菜單項(xiàng)下的是在這個(gè)新的菜單項(xiàng)下的屬屬性和選項(xiàng)性和選項(xiàng),其中,其中options部分有:部分有:a. 類(lèi)型定義:類(lèi)型定義: 每個(gè)每個(gè)config菜單

35、項(xiàng)都要有類(lèi)型定義,菜單項(xiàng)都要有類(lèi)型定義,bool:布爾類(lèi)型,:布爾類(lèi)型,tristate三態(tài):內(nèi)建、模塊、移除,三態(tài):內(nèi)建、模塊、移除,string:字符串,:字符串,hex:十:十六進(jìn)制,六進(jìn)制,integer:整型。:整型。編譯模塊進(jìn)內(nèi)核編譯模塊進(jìn)內(nèi)核37編譯模塊進(jìn)內(nèi)核編譯模塊進(jìn)內(nèi)核v(1)Kconfigvoptions部分有:部分有:a. 類(lèi)型定義:類(lèi)型定義:v例:例:config HELLO_MODULE bool hello test modulevbool 類(lèi)型類(lèi)型的只能選中或不選中,顯示為的只能選中或不選中,顯示為 ; vtristate類(lèi)型類(lèi)型的菜單項(xiàng)多了編譯成內(nèi)核模塊的選項(xiàng),

36、顯示為的菜單項(xiàng)多了編譯成內(nèi)核模塊的選項(xiàng),顯示為 , 假如選擇編譯成內(nèi)核模塊,則會(huì)在假如選擇編譯成內(nèi)核模塊,則會(huì)在.config中生成一個(gè)中生成一個(gè) CONFIG_HELLO_MODULE=m的配置,假如選擇內(nèi)建,就的配置,假如選擇內(nèi)建,就是直接編譯進(jìn)內(nèi)核,就會(huì)在是直接編譯進(jìn)內(nèi)核,就會(huì)在.config中生成一個(gè)中生成一個(gè) CONFIG_HELLO_MODULE=y的配置的配置38v(1)Kconfigvoptions部分有:部分有:b. 依賴(lài)型定義依賴(lài)型定義depends on或或requires指此菜單的出現(xiàn)是否依指此菜單的出現(xiàn)是否依賴(lài)于另一個(gè)定義賴(lài)于另一個(gè)定義:例如:例如:config HE

37、LLO_MODULE bool “hello test module” depends on ARCH_PXA這個(gè)例子表明這個(gè)例子表明HELLO_MODULE這個(gè)菜單項(xiàng)只對(duì)這個(gè)菜單項(xiàng)只對(duì)XScale處理處理器有效,即只有在選擇了器有效,即只有在選擇了ARCH_PXA,該菜單才可見(jiàn)(可配,該菜單才可見(jiàn)(可配置)。置)。編譯模塊進(jìn)內(nèi)核編譯模塊進(jìn)內(nèi)核39v(1)Kconfigvoptions部分有:部分有:c. 幫助性定義:幫助性定義: 只是增加幫助用關(guān)鍵字只是增加幫助用關(guān)鍵字help或或 -help-編譯模塊進(jìn)內(nèi)核編譯模塊進(jìn)內(nèi)核40編譯模塊進(jìn)內(nèi)核編譯模塊進(jìn)內(nèi)核v(1)Kconfig menu Ne

38、twork device support config NETDEVICES bool Enable Net Devices depends on NET default y help This is help desciption。.endmenu41編譯模塊進(jìn)內(nèi)核編譯模塊進(jìn)內(nèi)核v(1)Kconfig在在menu/endmenu中的內(nèi)容會(huì)成為中的內(nèi)容會(huì)成為Network device support的子菜單。的子菜單。每一個(gè)子菜單項(xiàng)都是由每一個(gè)子菜單項(xiàng)都是由config來(lái)定義的。來(lái)定義的。config下方的那些下方的那些bool、depends on、default、help等為等為conf

39、ig的屬性,用于定義該菜單項(xiàng)的類(lèi)型、依賴(lài)項(xiàng)、默認(rèn)值、的屬性,用于定義該菜單項(xiàng)的類(lèi)型、依賴(lài)項(xiàng)、默認(rèn)值、幫助信息等。幫助信息等。42編譯模塊進(jìn)內(nèi)核編譯模塊進(jìn)內(nèi)核v(1)Kconfig目錄層次迭代:目錄層次迭代:v在上級(jí)在上級(jí)Kconfig中有類(lèi)似語(yǔ)句:中有類(lèi)似語(yǔ)句: source “drivers/usb/Kconfig“或或 source drivers/misc/Kconfig“ 用來(lái)包含(或嵌套)新的用來(lái)包含(或嵌套)新的Kconfig文件,這樣便可以使各文件,這樣便可以使各個(gè)目錄管理各自的配置內(nèi)容,不必把那些配置都寫(xiě)在同一個(gè)文個(gè)目錄管理各自的配置內(nèi)容,不必把那些配置都寫(xiě)在同一個(gè)文件里,方便

40、修改和管理。件里,方便修改和管理。vmisc驅(qū)動(dòng)是一些擁有著共同特性的簡(jiǎn)單字符設(shè)備驅(qū)動(dòng)。所驅(qū)動(dòng)是一些擁有著共同特性的簡(jiǎn)單字符設(shè)備驅(qū)動(dòng)。所有的有的misc設(shè)備被分配同一個(gè)主設(shè)備號(hào)設(shè)備被分配同一個(gè)主設(shè)備號(hào)MISC_MAJOR(10),但是每一個(gè)可以選擇一個(gè)單獨(dú)的次設(shè)備號(hào)。但是每一個(gè)可以選擇一個(gè)單獨(dú)的次設(shè)備號(hào)。 43編譯模塊進(jìn)內(nèi)核編譯模塊進(jìn)內(nèi)核v(2)內(nèi)核的)內(nèi)核的Makefile內(nèi)核的內(nèi)核的Makefile分為分為5個(gè)組成部分:個(gè)組成部分: 1)Makefile 最頂層的最頂層的Makefile 2).config 內(nèi)核的當(dāng)前配置文件,編譯時(shí)成為頂層內(nèi)核的當(dāng)前配置文件,編譯時(shí)成為頂層Makefil

41、e的一部分的一部分 3)arch/$(ARCH)/Makefile 和體系結(jié)構(gòu)相關(guān)的和體系結(jié)構(gòu)相關(guān)的Makefile 4)s/Makefile.* 一些一些Makefile的通用規(guī)則的通用規(guī)則 5)kbuild Makefile 各級(jí)目錄下的大概約各級(jí)目錄下的大概約500個(gè)文件,編個(gè)文件,編譯時(shí)根據(jù)上層譯時(shí)根據(jù)上層Makefile傳下來(lái)的宏定義和其它編譯規(guī)則,將源傳下來(lái)的宏定義和其它編譯規(guī)則,將源代碼編譯成模塊或編入內(nèi)核。代碼編譯成模塊或編入內(nèi)核。 44編譯模塊進(jìn)內(nèi)核編譯模塊進(jìn)內(nèi)核v(2)Makefile頂層的頂層的Makefile文件文件讀取讀取 .config文件的內(nèi)容,并總體上文件的內(nèi)容

42、,并總體上負(fù)負(fù)責(zé)責(zé)build內(nèi)核和模塊內(nèi)核和模塊。Arch Makefile則提供則提供補(bǔ)充體系結(jié)構(gòu)相關(guān)的信息補(bǔ)充體系結(jié)構(gòu)相關(guān)的信息。 s目錄下的目錄下的Makefile文件包含了所有用來(lái)根據(jù)文件包含了所有用來(lái)根據(jù)kbuild Makefile 構(gòu)建內(nèi)核所需的定義和規(guī)則構(gòu)建內(nèi)核所需的定義和規(guī)則。45編譯模塊進(jìn)內(nèi)核編譯模塊進(jìn)內(nèi)核v(2)Makefileobj-$(CONFIG_HELLO) +=hello.o根據(jù)根據(jù).config文件的文件的CONFIG_ 變量來(lái)決定文件的編譯方式(變量來(lái)決定文件的編譯方式(編編譯進(jìn)內(nèi)核或編譯成模塊譯進(jìn)內(nèi)核或編譯成模塊)46v1)進(jìn)入)進(jìn)入2.6.24內(nèi)核,在內(nèi)

43、核,在driver/misc下建立下建立hello文件夾,文件夾,并編寫(xiě)一個(gè)名為并編寫(xiě)一個(gè)名為hello.c的模塊:的模塊: #include #include MODULE_LICENSE(“Dual BSD/GPL”);static int hello_init(void) printk(KERN_INFO “Hello world!n ); return 0;static void hello_exit(void) printk(KERN_INFO Goodbye world!n );module_init(hello_init);module_exit(hello_exit);實(shí)例實(shí)例

44、3:將模塊編譯進(jìn)內(nèi)核在:將模塊編譯進(jìn)內(nèi)核在arm開(kāi)發(fā)板上運(yùn)行開(kāi)發(fā)板上運(yùn)行47v2)建立)建立Kconfigv在在hello文件夾文件夾下建立下建立Kconfig,內(nèi)容如下:,內(nèi)容如下:menu “Hello Driver”comment “Hello Driver”config HELLOtristate “Hello support”help this is a hello diriver which can say “hello world!”;endmenu48v3)建立)建立Makefile在在hello文件夾文件夾下建立下建立Makefile,內(nèi)容如下:,內(nèi)容如下: obj-$(CO

45、NFIG_HELLO) +=hello.ov4)使)使Kconfig和和Makefile生效生效編輯編輯driver/misc/Kconfig,在,在if MISC_DEVICES下添加語(yǔ)句:下添加語(yǔ)句: source drivers/misc/hello/Kconfig編輯編輯driver/misc/Makefile,添加:,添加: obj-$(CONFIG_HELLO) +=hello.o/49v5)到內(nèi)核的頂層目錄,)到內(nèi)核的頂層目錄,執(zhí)行執(zhí)行sudo make menuconfig,選選中該驅(qū)動(dòng)中該驅(qū)動(dòng)在在Device driver- Mics devices- Hello Drive

46、r-50v5)到內(nèi)核的頂層目錄,)到內(nèi)核的頂層目錄,執(zhí)行執(zhí)行sudo make menuconfig,選選中該驅(qū)動(dòng)中該驅(qū)動(dòng)在在Device driver- Mics devices- Hello Driver-v按按 h 輸出幫助信息輸出幫助信息v按按 y ,出現(xiàn)個(gè),出現(xiàn)個(gè)*號(hào),表示將其編譯進(jìn)內(nèi)核號(hào),表示將其編譯進(jìn)內(nèi)核vM編譯為模塊編譯為模塊51v6)編譯:)編譯:#sudo make信息如下:信息如下:52v6)編譯:)編譯:編譯結(jié)果如下:編譯結(jié)果如下:53v7)把內(nèi)核燒入教學(xué)平臺(tái))把內(nèi)核燒入教學(xué)平臺(tái)啟動(dòng)信息如下:?jiǎn)?dòng)信息如下:有有hello world信息輸出,說(shuō)明已經(jīng)成功,信息輸出,說(shuō)明

47、已經(jīng)成功,hello驅(qū)動(dòng)已在內(nèi)核驅(qū)動(dòng)已在內(nèi)核中注冊(cè)。中注冊(cè)。54v8)把)把hello驅(qū)動(dòng)編譯成模塊:驅(qū)動(dòng)編譯成模塊:在第在第5步中,把驅(qū)動(dòng)選擇改成以模塊方式編譯,選步中,把驅(qū)動(dòng)選擇改成以模塊方式編譯,選M,如下:,如下:55v8)把)把hello驅(qū)動(dòng)編譯成模塊:驅(qū)動(dòng)編譯成模塊:再來(lái)編譯,看到它正以模塊的方式被編譯:再來(lái)編譯,看到它正以模塊的方式被編譯:56v8)把)把hello驅(qū)動(dòng)編譯成模塊:驅(qū)動(dòng)編譯成模塊:編譯結(jié)果:編譯結(jié)果:57v9)測(cè)試模塊)測(cè)試模塊在教學(xué)平臺(tái)啟動(dòng)進(jìn)入文件系統(tǒng)后,把在教學(xué)平臺(tái)啟動(dòng)進(jìn)入文件系統(tǒng)后,把hello.ko拷到拷到/lib/modules/2.6.24.2下,如果

48、沒(méi)有要事先建立。(下,如果沒(méi)有要事先建立。(#mkdir p /lib/modules/2.6.24.2)進(jìn)入目錄進(jìn)入目錄/lib/modules/2.6.24.2,通過(guò),通過(guò)insmod進(jìn)行掛載,進(jìn)行掛載,rmmod進(jìn)行卸載。進(jìn)行卸載。到此,一個(gè)簡(jiǎn)單的到此,一個(gè)簡(jiǎn)單的hello驅(qū)動(dòng)編譯進(jìn)內(nèi)核和編譯成模塊的實(shí)驗(yàn)驅(qū)動(dòng)編譯進(jìn)內(nèi)核和編譯成模塊的實(shí)驗(yàn)完成。完成。58v設(shè)備驅(qū)動(dòng)最通俗的解釋是設(shè)備驅(qū)動(dòng)最通俗的解釋是“驅(qū)使硬件設(shè)備行動(dòng)驅(qū)使硬件設(shè)備行動(dòng)”。v設(shè)備驅(qū)動(dòng)與底層硬件直接打交道,按照硬件設(shè)備的具體工作方式設(shè)備驅(qū)動(dòng)與底層硬件直接打交道,按照硬件設(shè)備的具體工作方式讀寫(xiě)設(shè)備寄存器,完成設(shè)備的輪詢(xún)、中斷、讀寫(xiě)

49、設(shè)備寄存器,完成設(shè)備的輪詢(xún)、中斷、DMA通信,進(jìn)行物理通信,進(jìn)行物理內(nèi)存向虛擬內(nèi)存的映射,最終使通信設(shè)備能夠收發(fā)數(shù)據(jù)。內(nèi)存向虛擬內(nèi)存的映射,最終使通信設(shè)備能夠收發(fā)數(shù)據(jù)。v設(shè)備驅(qū)動(dòng)的一個(gè)基本特征是設(shè)備處理的抽象概念。設(shè)備驅(qū)動(dòng)的一個(gè)基本特征是設(shè)備處理的抽象概念。嵌入式系統(tǒng)驅(qū)動(dòng)程序概述嵌入式系統(tǒng)驅(qū)動(dòng)程序概述59嵌入式系統(tǒng)驅(qū)動(dòng)程序概述嵌入式系統(tǒng)驅(qū)動(dòng)程序概述v在在Linux系統(tǒng)中,系統(tǒng)中,所有的外部設(shè)備所有的外部設(shè)備都被看作是目錄都被看作是目錄/dev下的一個(gè)下的一個(gè)文件文件,也就是系統(tǒng)把,也就是系統(tǒng)把外部設(shè)備當(dāng)作特殊文件來(lái)處理外部設(shè)備當(dāng)作特殊文件來(lái)處理,并為外部設(shè),并為外部設(shè)備提供一種備提供一種標(biāo)準(zhǔn)接

50、口標(biāo)準(zhǔn)接口,使得系統(tǒng)像訪(fǎng)問(wèn)文件一樣訪(fǎng)問(wèn)外部設(shè)備。,使得系統(tǒng)像訪(fǎng)問(wèn)文件一樣訪(fǎng)問(wèn)外部設(shè)備。v應(yīng)用程序通過(guò)調(diào)用應(yīng)用程序通過(guò)調(diào)用標(biāo)準(zhǔn)的設(shè)備文件操作函數(shù)標(biāo)準(zhǔn)的設(shè)備文件操作函數(shù)來(lái)打開(kāi)、關(guān)閉、讀取來(lái)打開(kāi)、關(guān)閉、讀取和寫(xiě)入設(shè)備。和寫(xiě)入設(shè)備。 v例如系統(tǒng)中的第一個(gè)例如系統(tǒng)中的第一個(gè)IDE硬盤(pán)被表示成硬盤(pán)被表示成/dev/had。60嵌入式系統(tǒng)驅(qū)動(dòng)程序概述嵌入式系統(tǒng)驅(qū)動(dòng)程序概述vLinux支持三類(lèi)硬件設(shè)備:支持三類(lèi)硬件設(shè)備:一類(lèi)是一類(lèi)是塊設(shè)備塊設(shè)備,類(lèi)似磁盤(pán)以記錄塊或扇區(qū)為單位,成塊進(jìn)行輸,類(lèi)似磁盤(pán)以記錄塊或扇區(qū)為單位,成塊進(jìn)行輸入入/輸出的設(shè)備;輸出的設(shè)備;另一類(lèi)是另一類(lèi)是字符設(shè)備字符設(shè)備,類(lèi)似鍵盤(pán)以字符為單位

51、,逐個(gè)進(jìn)行輸入,類(lèi)似鍵盤(pán)以字符為單位,逐個(gè)進(jìn)行輸入/輸出的設(shè)備。輸出的設(shè)備。第三類(lèi)是第三類(lèi)是網(wǎng)路設(shè)備網(wǎng)路設(shè)備是一種特殊設(shè)備;是一種特殊設(shè)備;/dev下沒(méi)有對(duì)應(yīng)于網(wǎng)絡(luò)設(shè)下沒(méi)有對(duì)應(yīng)于網(wǎng)絡(luò)設(shè)備的文件,正常的文件操作備的文件,正常的文件操作( read, write等等 )對(duì)于網(wǎng)絡(luò)設(shè)備沒(méi)對(duì)于網(wǎng)絡(luò)設(shè)備沒(méi)有意義。有意義。網(wǎng)絡(luò)設(shè)備可以通過(guò)套接口訪(fǎng)問(wèn)。網(wǎng)絡(luò)設(shè)備可以通過(guò)套接口訪(fǎng)問(wèn)。61v字符設(shè)備字符設(shè)備指那些指那些無(wú)需緩沖直接讀寫(xiě)的設(shè)備無(wú)需緩沖直接讀寫(xiě)的設(shè)備,字符設(shè)備接口只,字符設(shè)備接口只支持順支持順序存取序存取的功能。的功能。v塊設(shè)備塊設(shè)備則僅能以則僅能以塊為單位讀寫(xiě)塊為單位讀寫(xiě),典型的塊大小為,典型的塊大小

52、為512或或1024字節(jié)字節(jié)。塊。塊設(shè)備的存取是通過(guò)設(shè)備的存取是通過(guò)buffer cache來(lái)進(jìn)行來(lái)進(jìn)行并且可以并且可以隨機(jī)訪(fǎng)問(wèn)隨機(jī)訪(fǎng)問(wèn),即不管,即不管塊位于設(shè)備中何處都可以對(duì)其進(jìn)行讀寫(xiě)。塊設(shè)備可以通過(guò)塊位于設(shè)備中何處都可以對(duì)其進(jìn)行讀寫(xiě)。塊設(shè)備可以通過(guò)其設(shè)備相其設(shè)備相關(guān)文件關(guān)文件進(jìn)行訪(fǎng)問(wèn),但更為平常的訪(fǎng)問(wèn)方法是進(jìn)行訪(fǎng)問(wèn),但更為平常的訪(fǎng)問(wèn)方法是通過(guò)文件系統(tǒng)通過(guò)文件系統(tǒng)。文件系文件系統(tǒng)通常都建立在塊設(shè)備上。統(tǒng)通常都建立在塊設(shè)備上。v網(wǎng)絡(luò)設(shè)備網(wǎng)絡(luò)設(shè)備可以通過(guò)可以通過(guò)套接口訪(fǎng)問(wèn)套接口訪(fǎng)問(wèn)。嵌入式系統(tǒng)驅(qū)動(dòng)程序概述嵌入式系統(tǒng)驅(qū)動(dòng)程序概述62v塊(磁盤(pán))設(shè)備和字符設(shè)備的塊(磁盤(pán))設(shè)備和字符設(shè)備的設(shè)備相關(guān)文件

53、設(shè)備相關(guān)文件可以通過(guò)可以通過(guò)mknod命令命令來(lái)創(chuàng)建,并使用來(lái)創(chuàng)建,并使用主從設(shè)備號(hào)主從設(shè)備號(hào)來(lái)描述此設(shè)備。來(lái)描述此設(shè)備。v網(wǎng)絡(luò)設(shè)備也用網(wǎng)絡(luò)設(shè)備也用設(shè)備相關(guān)文件設(shè)備相關(guān)文件來(lái)表示,但來(lái)表示,但Linux尋找和初始化網(wǎng)絡(luò)尋找和初始化網(wǎng)絡(luò)設(shè)備時(shí)才建立這種文件。設(shè)備時(shí)才建立這種文件。v由同一個(gè)設(shè)備驅(qū)動(dòng)控制的所有設(shè)備具有相同的主設(shè)備號(hào),從設(shè)備由同一個(gè)設(shè)備驅(qū)動(dòng)控制的所有設(shè)備具有相同的主設(shè)備號(hào),從設(shè)備號(hào)則被用來(lái)區(qū)分具有相同主設(shè)備號(hào)且由相同設(shè)備驅(qū)動(dòng)控制的不同號(hào)則被用來(lái)區(qū)分具有相同主設(shè)備號(hào)且由相同設(shè)備驅(qū)動(dòng)控制的不同設(shè)備。設(shè)備。嵌入式系統(tǒng)驅(qū)動(dòng)程序概述嵌入式系統(tǒng)驅(qū)動(dòng)程序概述63嵌入式系統(tǒng)驅(qū)動(dòng)程序概述嵌入式系統(tǒng)驅(qū)動(dòng)

54、程序概述v設(shè)備驅(qū)動(dòng)程序?qū)嶋H是處理和操作硬件控制器的軟件,從本質(zhì)設(shè)備驅(qū)動(dòng)程序?qū)嶋H是處理和操作硬件控制器的軟件,從本質(zhì)上講,是內(nèi)核中具有最高特權(quán)級(jí)的、駐留內(nèi)存的、可共享的上講,是內(nèi)核中具有最高特權(quán)級(jí)的、駐留內(nèi)存的、可共享的底層硬件處理例程。底層硬件處理例程。v驅(qū)動(dòng)程序是內(nèi)核的一部分,是操作系統(tǒng)內(nèi)核與硬件設(shè)備的直驅(qū)動(dòng)程序是內(nèi)核的一部分,是操作系統(tǒng)內(nèi)核與硬件設(shè)備的直接接口,驅(qū)動(dòng)程序屏蔽了硬件的細(xì)節(jié)。接接口,驅(qū)動(dòng)程序屏蔽了硬件的細(xì)節(jié)。64嵌入式系統(tǒng)驅(qū)動(dòng)程序概述嵌入式系統(tǒng)驅(qū)動(dòng)程序概述v設(shè)備驅(qū)動(dòng)程序完成以下功能:設(shè)備驅(qū)動(dòng)程序完成以下功能:對(duì)設(shè)備初始化和釋放;對(duì)設(shè)備初始化和釋放;對(duì)設(shè)備進(jìn)行管理,包括實(shí)時(shí)參數(shù)設(shè)

55、置,以及提供對(duì)設(shè)備的對(duì)設(shè)備進(jìn)行管理,包括實(shí)時(shí)參數(shù)設(shè)置,以及提供對(duì)設(shè)備的操作接口;操作接口;讀取應(yīng)用程序傳送給設(shè)備文件的數(shù)據(jù)或者回送應(yīng)用程序請(qǐng)讀取應(yīng)用程序傳送給設(shè)備文件的數(shù)據(jù)或者回送應(yīng)用程序請(qǐng)求的數(shù)據(jù);求的數(shù)據(jù);檢測(cè)和處理設(shè)備出現(xiàn)的錯(cuò)誤。檢測(cè)和處理設(shè)備出現(xiàn)的錯(cuò)誤。65vLinux操作系統(tǒng)將所有的設(shè)備全部看成文件,并通過(guò)文件的操操作系統(tǒng)將所有的設(shè)備全部看成文件,并通過(guò)文件的操作界面進(jìn)行操作。作界面進(jìn)行操作。v對(duì)用戶(hù)程序而言,設(shè)備驅(qū)動(dòng)程序隱藏了設(shè)備的具體細(xì)節(jié),對(duì)各對(duì)用戶(hù)程序而言,設(shè)備驅(qū)動(dòng)程序隱藏了設(shè)備的具體細(xì)節(jié),對(duì)各種不同設(shè)備提供了一致的接口,一般來(lái)說(shuō),是把設(shè)備映射為一種不同設(shè)備提供了一致的接口,一

56、般來(lái)說(shuō),是把設(shè)備映射為一個(gè)特殊的設(shè)備文件,用戶(hù)程序可以像對(duì)其他文件一樣對(duì)此設(shè)備個(gè)特殊的設(shè)備文件,用戶(hù)程序可以像對(duì)其他文件一樣對(duì)此設(shè)備文件進(jìn)行操作。文件進(jìn)行操作。66v這意味著:這意味著:由于每一個(gè)設(shè)備至少由文件系統(tǒng)的一個(gè)文件代表,因而都有由于每一個(gè)設(shè)備至少由文件系統(tǒng)的一個(gè)文件代表,因而都有一個(gè)一個(gè)“文件名文件名”。應(yīng)用程序通??梢酝ㄟ^(guò)系統(tǒng)調(diào)用應(yīng)用程序通常可以通過(guò)系統(tǒng)調(diào)用open()打開(kāi)設(shè)備文件,建立打開(kāi)設(shè)備文件,建立起與目標(biāo)設(shè)備的連接。起與目標(biāo)設(shè)備的連接。打開(kāi)了代表著目標(biāo)設(shè)備的文件,即建立起與設(shè)備的連接后,打開(kāi)了代表著目標(biāo)設(shè)備的文件,即建立起與設(shè)備的連接后,可以通過(guò)可以通過(guò)read()、wri

57、te()、ioctl()等常規(guī)的文件操作對(duì)目標(biāo)等常規(guī)的文件操作對(duì)目標(biāo)設(shè)備進(jìn)行操作。設(shè)備進(jìn)行操作。67嵌入式系統(tǒng)驅(qū)動(dòng)程序結(jié)構(gòu)嵌入式系統(tǒng)驅(qū)動(dòng)程序結(jié)構(gòu)v在系統(tǒng)內(nèi)部,在系統(tǒng)內(nèi)部,I/O設(shè)備的存取通過(guò)一組固定的入口點(diǎn)來(lái)進(jìn)行,入設(shè)備的存取通過(guò)一組固定的入口點(diǎn)來(lái)進(jìn)行,入口點(diǎn)也可以理解為設(shè)備的句柄,就是對(duì)設(shè)備進(jìn)行操作的基本函口點(diǎn)也可以理解為設(shè)備的句柄,就是對(duì)設(shè)備進(jìn)行操作的基本函數(shù)。字符型設(shè)備驅(qū)動(dòng)程序提供如下幾個(gè)入口點(diǎn):數(shù)。字符型設(shè)備驅(qū)動(dòng)程序提供如下幾個(gè)入口點(diǎn):open入口點(diǎn)。打開(kāi)設(shè)備準(zhǔn)備入口點(diǎn)。打開(kāi)設(shè)備準(zhǔn)備I/O操作。對(duì)字符設(shè)備文件進(jìn)行操作。對(duì)字符設(shè)備文件進(jìn)行打開(kāi)操作,都會(huì)調(diào)用設(shè)備的打開(kāi)操作,都會(huì)調(diào)用設(shè)備的o

58、pen入口點(diǎn)。入口點(diǎn)。open子程序必須子程序必須對(duì)將要進(jìn)行的對(duì)將要進(jìn)行的I/O操作做好必要的準(zhǔn)備工作,如清除緩沖區(qū)操作做好必要的準(zhǔn)備工作,如清除緩沖區(qū)等。如果設(shè)備是獨(dú)占的,即同一時(shí)刻只能有一個(gè)程序訪(fǎng)問(wèn)此等。如果設(shè)備是獨(dú)占的,即同一時(shí)刻只能有一個(gè)程序訪(fǎng)問(wèn)此設(shè)備,則設(shè)備,則open子程序必須設(shè)置一些標(biāo)志以表示設(shè)備處于忙子程序必須設(shè)置一些標(biāo)志以表示設(shè)備處于忙狀態(tài)。狀態(tài)。68嵌入式系統(tǒng)驅(qū)動(dòng)程序結(jié)構(gòu)嵌入式系統(tǒng)驅(qū)動(dòng)程序結(jié)構(gòu)vclose入口點(diǎn)。關(guān)閉一個(gè)設(shè)備。當(dāng)最后一次使用設(shè)備完成后,調(diào)用入口點(diǎn)。關(guān)閉一個(gè)設(shè)備。當(dāng)最后一次使用設(shè)備完成后,調(diào)用close子程序。獨(dú)占設(shè)備必須標(biāo)記設(shè)備方可再次使用。子程序。獨(dú)占設(shè)備

59、必須標(biāo)記設(shè)備方可再次使用。vread入口點(diǎn)。從設(shè)備上讀數(shù)據(jù)。對(duì)于有緩沖區(qū)的入口點(diǎn)。從設(shè)備上讀數(shù)據(jù)。對(duì)于有緩沖區(qū)的I/O操作,一般是操作,一般是從緩沖區(qū)里讀數(shù)據(jù)。對(duì)字符設(shè)備文件進(jìn)行讀操作將調(diào)用從緩沖區(qū)里讀數(shù)據(jù)。對(duì)字符設(shè)備文件進(jìn)行讀操作將調(diào)用read子程子程序。序。69嵌入式系統(tǒng)驅(qū)動(dòng)程序結(jié)構(gòu)嵌入式系統(tǒng)驅(qū)動(dòng)程序結(jié)構(gòu)vwrite入口點(diǎn)。往設(shè)備上寫(xiě)數(shù)據(jù)。對(duì)于有緩沖區(qū)的入口點(diǎn)。往設(shè)備上寫(xiě)數(shù)據(jù)。對(duì)于有緩沖區(qū)的I/O操作,一般操作,一般是把數(shù)據(jù)寫(xiě)入緩沖區(qū)里。是把數(shù)據(jù)寫(xiě)入緩沖區(qū)里。vioctl入口點(diǎn)。執(zhí)行讀、寫(xiě)之外的操作。入口點(diǎn)。執(zhí)行讀、寫(xiě)之外的操作。vselect入口點(diǎn)。檢查設(shè)備,看數(shù)據(jù)是否可讀或設(shè)備是否可用

60、于寫(xiě)入口點(diǎn)。檢查設(shè)備,看數(shù)據(jù)是否可讀或設(shè)備是否可用于寫(xiě)數(shù)據(jù)。數(shù)據(jù)。select系統(tǒng)調(diào)用在檢查與設(shè)備文件相關(guān)的文件描述符時(shí)使系統(tǒng)調(diào)用在檢查與設(shè)備文件相關(guān)的文件描述符時(shí)使用用select入口點(diǎn)。入口點(diǎn)。70嵌入式系統(tǒng)驅(qū)動(dòng)程序結(jié)構(gòu)嵌入式系統(tǒng)驅(qū)動(dòng)程序結(jié)構(gòu)vLinux系統(tǒng)設(shè)備驅(qū)動(dòng)程序系統(tǒng)設(shè)備驅(qū)動(dòng)程序三個(gè)重要數(shù)據(jù)結(jié)構(gòu)三個(gè)重要數(shù)據(jù)結(jié)構(gòu):file_operation(文件操作)(文件操作)file(文件)(文件)inode(節(jié)點(diǎn))(節(jié)點(diǎn))v定義在定義在include/linux/fs.h文件中文件中71嵌入式系統(tǒng)驅(qū)動(dòng)程序結(jié)構(gòu)嵌入式系統(tǒng)驅(qū)動(dòng)程序結(jié)構(gòu)vfile_operation將系統(tǒng)調(diào)用和驅(qū)動(dòng)關(guān)聯(lián)起來(lái),用來(lái)存儲(chǔ)內(nèi)核驅(qū)動(dòng)

溫馨提示

  • 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ì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論