第2章 構(gòu)造和運(yùn)行模塊_第1頁
第2章 構(gòu)造和運(yùn)行模塊_第2頁
第2章 構(gòu)造和運(yùn)行模塊_第3頁
第2章 構(gòu)造和運(yùn)行模塊_第4頁
第2章 構(gòu)造和運(yùn)行模塊_第5頁
已閱讀5頁,還剩31頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

152第2章構(gòu)造和運(yùn)行模塊HelloWorld模塊模塊與應(yīng)用程序模塊的編譯和加載內(nèi)核符號表初始化和關(guān)閉模塊參數(shù)346HelloWorld模塊#include<linux/init.h>#include<linux/module.h>#include<linux/kernel.h>MODULE_LICENSE("DualBSD/GPL");

staticint

hello_init(void){

printk(KERN_ALERT"Hello,world\n"); return0;}staticvoidhello_exit(void){

printk(KERN_ALERT"Goodbye,cruelworld\n");}module_init(hello_init);module_exit(hello_exit);

HelloWorld模塊編譯%makemake[1]:Enteringdirectory`/usr/src/linux-2.6.10‘CC[M]/home/ldd3/src/misc-modules/hello.oBuildingmodules,stage2.MODPOSTCC/home/ldd3/src/misc-modules/hello.mod.oLD[M]/home/ldd3/src/misc-modules/hello.komake[1]:Leavingdirectory`/usr/src/linux-2.6.10'%su

root#insmod./hello.koHello,worldroot#rmmodhelloGoodbyecruelworldroot#

HelloWorld模塊模塊常用的一些宏MODULE_AUTHOR(author);聲明模塊的作者M(jìn)ODULE_DESCRIPTION(description);說明模塊的用途MODULE_VERSION(version_string);聲明模塊的修訂號MODULE_DEVICE_TABLE(table_info);說明模塊所支持的設(shè)備MODULE_ALIAS(alternate_name);說明模塊的別名EXPORT_SYMBOL(symbol);聲明模塊導(dǎo)出的符號EXPORT_SYMBOL_GPL(symbol);聲明模塊導(dǎo)出的符號152第2章構(gòu)造和運(yùn)行模塊HelloWorld模塊模塊與應(yīng)用程序模塊的編譯和加載內(nèi)核符號表初始化和關(guān)閉模塊參數(shù)346模塊與應(yīng)用程序應(yīng)用程序從頭至尾執(zhí)行單個(gè)任務(wù),運(yùn)行在用戶空間核心模塊可根據(jù)需要加載、卸載加載時(shí)初始化并注冊自己,然后等待服務(wù)于將來的某個(gè)請求,類似于事件驅(qū)動的編程退出時(shí)必須自己清理現(xiàn)場(撤銷初始化函數(shù)所做的一切)只能使用內(nèi)核導(dǎo)出的符號(函數(shù)與變量),不能使用函數(shù)庫libc運(yùn)行在內(nèi)核空間模塊與應(yīng)用程序內(nèi)核空間和用戶空間03G4G0X虛擬地址空間內(nèi)存空間物理內(nèi)存PAGE_OFFSET用戶空間內(nèi)核空間內(nèi)核空間地址與物理內(nèi)存地只差一偏移量,故內(nèi)核空間地址(虛地址)到內(nèi)存空間地址的轉(zhuǎn)換是直接的,不需經(jīng)頁表模塊與應(yīng)用程序內(nèi)核空間和用戶空間03G4G0X虛擬地址空間PAGE_OFFSET用戶空間內(nèi)核空間xx頁yy頁xx頁yy頁頁表用戶空間地址(虛地址)到內(nèi)存空間地址的轉(zhuǎn)換必需經(jīng)頁表內(nèi)存空間物理內(nèi)存模塊與應(yīng)用程序內(nèi)核中的并發(fā)內(nèi)核編程與常見應(yīng)用程序編程的區(qū)別在于對并發(fā)的處理,內(nèi)核代碼(包括驅(qū)動)必須是可重入的,必須能夠同時(shí)運(yùn)行在多個(gè)上下文中。產(chǎn)生并發(fā)的原因Linux是多任務(wù)系統(tǒng),同時(shí)運(yùn)行多個(gè)進(jìn)程產(chǎn)生中斷內(nèi)核定時(shí)器對稱多處理器(SMP)2.6內(nèi)核可搶占,在單處理器上也存在類似多處理器的并發(fā)模塊與應(yīng)用程序當(dāng)前進(jìn)程由指向當(dāng)前進(jìn)程控制塊struct

task_struct

的指針current可獲得當(dāng)前進(jìn)程current->comm:當(dāng)前進(jìn)程命令名current->pid

:當(dāng)前進(jìn)程ID早期版本中current為一個(gè)全局變量,在2.6中,current存放在內(nèi)核棧中內(nèi)核棧大小為4096B,由用戶進(jìn)程與內(nèi)核進(jìn)程共享,不要聲明大的自動變量152第2章構(gòu)造和運(yùn)行模塊HelloWorld模塊模塊與應(yīng)用程序模塊的編譯和加載內(nèi)核符號表初始化和關(guān)閉模塊參數(shù)346模塊的編譯和裝載編譯模塊模塊不是獨(dú)立的可執(zhí)行程序,需要依賴核心才能工作,需要使用核心導(dǎo)出的符號,例printk()模塊不能單獨(dú)編譯,應(yīng)該用核心的構(gòu)造系統(tǒng)來構(gòu)造,即使用編譯核心時(shí)所使用的編譯器、鏈接器工具及同樣的內(nèi)核源代碼樹環(huán)境模塊可放在內(nèi)核源碼代碼樹中構(gòu)造也可放在內(nèi)核源代碼樹外構(gòu)造模塊的編譯和裝載放在內(nèi)核源代碼樹中設(shè)備驅(qū)動程存放在內(nèi)核源代碼樹根目錄drivers/的子目錄下,例如:字符設(shè)備:drivers/char/塊設(shè)備:drivers/block/USB設(shè)備:drivers/usb/char下有子目錄,也有文件,驅(qū)動程序源碼是放在該目錄下還是創(chuàng)建一個(gè)自己的子目錄?模塊的編譯和裝載放在drivers/char/下拷貝hello.c到drivers/char/目錄下打開drivers/char/Makefile,在其中增加一行:obj-m+=hello.o或若有配置選項(xiàng),增加如下一行:obj-$(CONFIG_HELLO)+=hello.o

打開配置文件drivers/char/Kconfig,在其中增加一項(xiàng):configHELLOtristate“NewHello”makemenuconfigmakemodules在何處執(zhí)行make?模塊的編譯和裝載放在drivers/char/下的子目錄中在drivers/char/下創(chuàng)建子目錄hello拷貝hello.c到drivers/char/hello/目錄下打開drivers/char/Makefile,在其中增加一行:obj-m

+=hello/

或若有配置選項(xiàng),增加如下一行:obj-$(CONFIG_HELLO)+=hello/

在drivers/char/hello/下新建Makefile,需一行:obj-m+=fishing.o

或若有配置選項(xiàng):obj-$(CONFIG_HELLO)+=hello.o

模塊的編譯和裝載打開配置文件drivers/char/Kconfig,在其中增加一項(xiàng):configHELLOtristate“NewHello”makemenuconfigmakemodules模塊的編譯和裝載放在內(nèi)核源代碼外設(shè)放在/home/ldd下,則需在該目錄中新建一Makefile,只需一行:obj-m:=hello.o運(yùn)行命令make-C/kernel/source/locationSUBDIRS=$PWDmodules或使用帶條件語句的復(fù)雜makefile(見后)模塊的編譯和裝載加載卸載模塊insmodmodule需指定模塊的完整文件名及路徑modprobemodulemodprobe只能從標(biāo)準(zhǔn)的已安裝模塊目錄中搜索需要裝入的模塊(/lib/modules/(shelluname–r))rmmodmodulemodprobermodules模塊的編譯和裝載helloworld的編譯建hello目錄,將hello.c與makefile放入其下,makefile中只需一行:Obj-m:=hello.o在hello目錄下運(yùn)行命令:make-C~/kernel-2.6M=$PWDmodules

或使用帶條件語句的復(fù)雜makefile(見后)模塊的編譯和裝載帶條件語句的makefile:在hello目錄下運(yùn)行命令make#IfKERNELRELEASEisdefined,we'vebeeninvokedfromthe#kernelbuildsystemandcanuseitslanguage.ifneq($(KERNELRELEASE),)

obj-m:=hello.o#Otherwisewewerecalleddirectlyfromthecommand#line;invokethekernelbuildsystem.else KERNELDIR?=/lib/modules/$(shelluname-r)/build PWD:=$(shellpwd)default: $(MAKE)-C$(KERNELDIR)M=$(PWD)modulesendif152第2章構(gòu)造和運(yùn)行模塊HelloWorld模塊模塊與應(yīng)用程序模塊的編譯和加載內(nèi)核符號表初始化和關(guān)閉模塊參數(shù)346內(nèi)核符號表內(nèi)核符號表中包含了所有全局內(nèi)核項(xiàng)(函數(shù)和變量)的地址,這是實(shí)現(xiàn)模塊化驅(qū)動程序所必需的,當(dāng)模塊被裝入內(nèi)核后,它所導(dǎo)出的任何符號都會成為內(nèi)核符號表的一部分。模塊可導(dǎo)出符號供其他模塊使用,也可不導(dǎo)出任何符號,只實(shí)現(xiàn)自己的功能利用模塊導(dǎo)出的符號可以在已有模塊基礎(chǔ)上層疊新模塊,這稱為模塊層疊技術(shù)模塊層疊技術(shù)可將復(fù)雜模塊分為幾層,然后從上到下逐層實(shí)現(xiàn),以減化實(shí)現(xiàn)的復(fù)雜性內(nèi)核符號表例如video-for-linux

驅(qū)動程序組劃分出了一個(gè)通用模塊,它導(dǎo)出的符號可供下層與具體硬件相關(guān)的驅(qū)動程序使用。根據(jù)所安裝的具體硬件的不同,可以加載通用的video模塊以及與具體硬件相關(guān)的特定模塊msdos文件依賴fat模塊導(dǎo)出的符號USB輸入設(shè)備模塊層疊在usbcore和input模塊之上Modprobe是處理模塊層疊的一個(gè)實(shí)用工具如何向內(nèi)核導(dǎo)出符號?EXPORT_SYMBOL(name);EXPORT_SYMBOL_GPL(nam)152第2章構(gòu)造和運(yùn)行模塊HelloWorld模塊模塊與應(yīng)用程序模塊的編譯和加載內(nèi)核符號表初始化和關(guān)閉模塊參數(shù)346初始化和關(guān)閉初始化模塊的初始化函數(shù)負(fù)責(zé)注冊模塊所提供的任何設(shè)施。這里的設(shè)施指的是一個(gè)可以被應(yīng)用程序訪問的新功能,它也可能是一個(gè)完整的驅(qū)動程序或者僅僅是一個(gè)軟件抽象。初始化函數(shù)定義:staticint

__init

initialization_function(void){ /*Initializationcodehere*/}module_init(initialization_function);

初始化和關(guān)閉__init修飾標(biāo)記表示在模塊裝載之后,模塊裝載器就會將初始化函數(shù)扔掉,以釋放其占用的內(nèi)存資源__initdata

與__init類似,只不過用于修飾數(shù)據(jù)內(nèi)核源代碼中可能還會碰到__devinit

和__devinitdata

,此兩修飾符只有在內(nèi)核未被配置為支持熱插拔時(shí)被翻譯為__init

和__initdata初始化和關(guān)閉清除函數(shù)清除函數(shù)負(fù)責(zé)在模塊被卸載前注銷接口并向系統(tǒng)中返回所有資源。清除函數(shù)定義:清除函數(shù)沒有返回值__exit表示該代碼僅用于模塊卸載staticvoid__exit

cleanup_function(void){ /*Cleanupcodehere*/}module_exit(cleanup_function);

初始化和關(guān)閉初始化過程中的錯(cuò)誤處理int__initmy_init_function(void){

interr; /*registrationtakesapointerandaname*/ err=register_this(ptr1,"skull"); if(err)goto

fail_this; err=register_that(ptr2,"skull"); if(err)goto

fail_that; err=register_those(ptr3,"skull"); if(err)goto

fail_those; return0;/*success*/

fail_those:unregister_that(ptr2,"skull");

fail_that:unregister_this(ptr1,"skull");

fail_this:returnerr;/*propagatetheerror*/}

初始化和關(guān)閉模塊的清除函數(shù)需要撤銷初始化函數(shù)所注冊的所有設(shè)施void__exitmy_cleanup_function(void){ unregister_those(ptr3,"skull"); unregister_that(ptr2,"skull"); unregister_this(ptr1,"skull"); return;}

152第2章構(gòu)造和運(yùn)行模塊HelloWorld模塊模塊與應(yīng)用程序模塊的編譯和加載內(nèi)核符號表初始化和關(guān)閉模塊參數(shù)346模塊參數(shù)應(yīng)用程序可帶參數(shù)運(yùn)行,模塊裝載時(shí)若也能帶參數(shù),將會增強(qiáng)模塊的適應(yīng)性insmod/modprobe執(zhí)行時(shí)可指定模塊參數(shù),modprobe還可從其配置文件/etc/modprobe.conf

中讀取參數(shù)怎么給模塊增加參數(shù)?module_param(name,type,perm);模塊參數(shù)例給helloworld模塊增加參數(shù)staticchar*whom="world";staticint

howmany=1;module_param(howmany,int,S_IRUGO);module_param(whom,charp,S_IRUGO);staticint

hello_init(void){

inti;for(i=0;i<howmany;i++)

printk(KERN_ALERT"(%d)Hello,%s\n",i,whom);return0;}staticvoidhello_exit(void){

printk(KERN_ALERT"Goodbye,cruelworld\n");}module_init(hello_init);module_exit(hello_exit);#include<linux/init.h>#include<linux/module.h>#include<li

溫馨提示

  • 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)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論