Linux內(nèi)核模塊編程_第1頁(yè)
Linux內(nèi)核模塊編程_第2頁(yè)
Linux內(nèi)核模塊編程_第3頁(yè)
Linux內(nèi)核模塊編程_第4頁(yè)
Linux內(nèi)核模塊編程_第5頁(yè)
已閱讀5頁(yè),還剩28頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

Linux內(nèi)核模塊編程主要參考書(shū)目《Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解(第2版)》宋寶華編著人民郵電出版社主要參考書(shū)目《Linux設(shè)備驅(qū)動(dòng)程序(第三版)》魏永明耿岳等譯中國(guó)電力出版社主要參考書(shū)目《精通Linux驅(qū)動(dòng)程序開(kāi)發(fā)》Sreekrishnan編著人民郵電出版社操作系統(tǒng)主要功能:CPU管理存儲(chǔ)管理設(shè)備管理文件管理網(wǎng)絡(luò)與通信管理用戶接口POSIX表示可移植操作系統(tǒng)接口(PortableOperatingSystemInterface)是為解決應(yīng)用程序平臺(tái)移植性提出的一種標(biāo)準(zhǔn)。Linux是什么?Linux是一個(gè)由幾百萬(wàn)行源代碼組成的龐大、復(fù)雜的程序,任何人都能從上下載。Linux是一套免費(fèi)的、源代碼開(kāi)放的、符合POSIX標(biāo)準(zhǔn)標(biāo)準(zhǔn)的操作系統(tǒng)。嚴(yán)格來(lái)說(shuō),Linux只包含以下圖中內(nèi)核與系統(tǒng)調(diào)用接口那兩層。Linux內(nèi)核的構(gòu)成8Linux的虛擬內(nèi)存管理Linux的虛擬內(nèi)存管理機(jī)制為應(yīng)用程序和驅(qū)動(dòng)程序提供了兩種效勞:使每個(gè)進(jìn)程都擁有自己獨(dú)立的內(nèi)存地址空間;對(duì)于32位Linux而言,每個(gè)任務(wù)可尋址的內(nèi)存地址空間都為0x00000000~0xFFFFFFFF(232,4GB)當(dāng)物理內(nèi)存不夠4GB時(shí),虛擬內(nèi)存管理模塊會(huì)用外存空間模擬內(nèi)存空間,并且該模擬過(guò)程對(duì)應(yīng)用程序是透明的。9用戶地址空間與內(nèi)核地址空間Linux將每個(gè)進(jìn)程的4GB的獨(dú)立地址空間又劃分為用戶地址空間(0x00000000~0xBFFFFFFF)和內(nèi)核地址空間(0xC0000000~0xFFFFFFFF)兩局部。操作系統(tǒng)內(nèi)核代碼和數(shù)據(jù)存放在內(nèi)核地址空間;每個(gè)進(jìn)程自己私有的代碼和數(shù)據(jù)存放在用戶地址空間雖然Linux的內(nèi)核代碼和數(shù)據(jù)被映射到了每個(gè)進(jìn)程的地址空間中〔所有進(jìn)程看到的內(nèi)容是相同的〕,但在實(shí)際的物理內(nèi)存中,只有內(nèi)核代碼和數(shù)據(jù)的一份拷貝。10用戶地址空間與內(nèi)核地址空間虛擬頁(yè)物理頁(yè)031null213null虛擬頁(yè)物理頁(yè)021null213null虛擬頁(yè)物理頁(yè)0null1null213null物理頁(yè)taken進(jìn)程id0Nnull1Yos2Y23Y1進(jìn)程1的頁(yè)表進(jìn)程id虛擬頁(yè)硬盤中的地址進(jìn)程2的頁(yè)表進(jìn)程3的頁(yè)表內(nèi)頁(yè)表外頁(yè)表CR3寄存器CPU負(fù)責(zé)查表(虛擬地址->物理地址),查表失敗時(shí)觸發(fā)缺頁(yè)中斷(14號(hào));OS負(fù)責(zé)填充各個(gè)表的內(nèi)容,并提供缺頁(yè)中斷的中斷效勞器程序。用戶態(tài)與核心態(tài)一般現(xiàn)代CPU都有幾種不同的指令執(zhí)行級(jí)別在高執(zhí)行級(jí)別下,代碼可以執(zhí)行特權(quán)指令,訪問(wèn)任意的物理地址,這種CPU執(zhí)行級(jí)別就對(duì)應(yīng)著內(nèi)核態(tài)用戶態(tài)指相應(yīng)的低級(jí)別執(zhí)行狀態(tài),代碼的掌控范圍會(huì)受到限制,只能執(zhí)行CPU指令集的一個(gè)子集舉例:intelx86CPU有四種不同的執(zhí)行級(jí)別0-3,Linux只使用了其中的0級(jí)和3級(jí)分別來(lái)表示內(nèi)核態(tài)和用戶態(tài)0xc0000000以上的內(nèi)核地址空間只能在內(nèi)核態(tài)下訪問(wèn),0x00000000-0xbfffffff的用戶地址空間在兩種狀態(tài)下都可以訪問(wèn)應(yīng)用程序可以通過(guò)Linux系統(tǒng)調(diào)用由用戶態(tài)進(jìn)入內(nèi)核態(tài)Linux進(jìn)程狀態(tài)Linux中任務(wù)和進(jìn)程是相同的術(shù)語(yǔ),每個(gè)進(jìn)程由task_struct結(jié)構(gòu)來(lái)描述,即PCB〔進(jìn)程控制塊〕Linux將進(jìn)程狀態(tài)主要分為五種:TASK_RUNNINGTASK_INTERRUPTIBLETASK_UNINTERRUPTIBLETASK_STOPPEDTASK_ZOMBILE。進(jìn)程的狀態(tài)隨著進(jìn)程的調(diào)度發(fā)生改變Linux進(jìn)程狀態(tài)轉(zhuǎn)換可裝載內(nèi)核模塊為了使系統(tǒng)功能能夠更靈活的擴(kuò)充,Linux支持內(nèi)核的動(dòng)態(tài)擴(kuò)展,即在系統(tǒng)運(yùn)行時(shí)給內(nèi)核增加新的功能〔即模塊module〕。模塊〔module〕是一段可以被動(dòng)態(tài)鏈接的目標(biāo)代碼〔.ko〕,它可由insmod命令動(dòng)態(tài)的裝載并鏈接到正在運(yùn)行的內(nèi)核。鏈接后,它就成了內(nèi)核的一局部,直到用rmmod命令解除鏈接并卸載。Linux驅(qū)動(dòng)程序就是一種特殊的內(nèi)核模塊。內(nèi)核模塊與應(yīng)用程序的不同內(nèi)核模塊工作在內(nèi)核空間〔supervisorspace〕,而應(yīng)用程序工作在用戶空間〔userspace〕內(nèi)核模塊是一個(gè)由多個(gè)回調(diào)函數(shù)組成的“被動(dòng)”代碼集合體,采用了“事件驅(qū)動(dòng)模型”;而應(yīng)用程序總是從頭至尾的執(zhí)行單個(gè)任務(wù)。內(nèi)核模塊不能調(diào)用C標(biāo)準(zhǔn)函數(shù)庫(kù)〔glibc庫(kù)〕,只能調(diào)用linux內(nèi)核導(dǎo)出的內(nèi)核函數(shù)。內(nèi)核模塊在編程時(shí)必須考慮可重入性〔reentrant〕內(nèi)核模塊可使用的棧很小(一般只有4096字節(jié))。內(nèi)核模塊程序源碼的構(gòu)成頭文件

#include<linux/init.h>#include<linux/module.h>必選許可聲明MODULE_LICENSE("DualBSD/GPL");必選加載函數(shù)staticint__inithello_init(void)必選卸載函數(shù)staticvoid__exithello_exit(void)必選模塊參數(shù)module_param(num,int,S_IRUGO)可選模塊導(dǎo)出符號(hào)EXPORT_SYMBOL(add_integer)可選模塊作者等信息聲明MODULE_AUTHOR(“author_name”)可選最簡(jiǎn)單的KernelModule#include<linux/init.h>#include<linux/module.h>MODULE_LICENSE("DualBSD/GPL");staticint__inithello_init(void){//這是模塊加載函數(shù)printk(KERN_ALERT"Hello,world\n");return0;}staticvoid__exithello_exit(void){//這是模塊卸載函數(shù)printk(KERN_ALERT"Goodbye,cruelworld\n");}module_init(hello_init);module_exit(hello_exit);模塊加載函數(shù)通過(guò)insmod或modprobe命令加載內(nèi)核模塊時(shí),模塊的加載函數(shù)會(huì)自動(dòng)被內(nèi)核執(zhí)行,完成模塊的相關(guān)初始化工作,通常包括:(1)向內(nèi)核注冊(cè)一些數(shù)據(jù)結(jié)構(gòu);〔2〕申請(qǐng)軟硬件資源;〔3〕初始化硬件模塊加載函數(shù)必須用宏“module_init”指定,它返回整型值。假設(shè)初始化成功那么返回0,假設(shè)失敗那么返回一個(gè)負(fù)值作為錯(cuò)誤碼。“__init”和“__exit”都是宏,利用了gcc的擴(kuò)展關(guān)鍵字,分別要求編譯器將所聲明函數(shù)的目標(biāo)代碼放入“init.text”段和“exit.text”段中(兩個(gè)特殊的ELF段)。static關(guān)鍵字為了將該函數(shù)名的可見(jiàn)性控制在本文件內(nèi)。#define__init__attribute__((__section__(“.init.text”)))#define__exit__attribute__((__section__(“.exit.text”)))module_init背后的秘密#definemodule_init(x)__initcall(x);#define__initcall(fn)device_initcall(fn)#definedevice_initcall(fn)__define_initcall("6",fn,6)#define__define_initcall(level,fn,id)\staticinitcall_t__initcall_##fn##id__used\__attribute__((__section__(".initcall"level".init")))=fn所以,module_init(x)最終展開(kāi)為:staticinitcall_t__initcall_##fn##id__used\__attribute__((__section__(".initcall"level".init")))=fninitcall_t是一個(gè)指向函數(shù)的指針類型typedefint(*initcall_t)(void)所以module_init本質(zhì)上是將一個(gè)函數(shù)指針變量放在了一名為".initcall6.init"ELF節(jié)中。ExecutableandLinkingFormat模塊卸載函數(shù)模塊卸載函數(shù)必須用宏“module_exit”指定,無(wú)返回值。當(dāng)通過(guò)rmmod命令卸載某模塊時(shí),模塊的卸載函數(shù)會(huì)自動(dòng)被內(nèi)核執(zhí)行,完成與模塊裝載函數(shù)相反的功能?!沧N一些內(nèi)核數(shù)據(jù)結(jié)構(gòu),釋放資源等〕。內(nèi)核打印函數(shù)printkprintk〔fmt,args…)級(jí)別KERN_EMERG用于緊急消息,常常是那些崩潰前的消息.KERN_ALERT需要立刻動(dòng)作的情形.KERN_CRIT嚴(yán)重情況,常常與嚴(yán)重的硬件或者軟件失效有關(guān).KERN_ERR用來(lái)報(bào)告錯(cuò)誤情況;設(shè)備驅(qū)動(dòng)常常使用KERN_ERR來(lái)報(bào)告硬件故障.KERN_WARNING有問(wèn)題的情況的警告,這些情況自己不會(huì)引起系統(tǒng)的嚴(yán)重問(wèn)題.KERN_NOTICE正常情況,但是仍然值得注意.在這個(gè)級(jí)別一些平安相關(guān)的情況會(huì)報(bào)告.KERN_INFO信息型消息.在這個(gè)級(jí)別,很多驅(qū)動(dòng)在啟動(dòng)時(shí)打印它們發(fā)現(xiàn)的硬件的信息.KERN_DEBUG用作調(diào)試消息.不能打印浮點(diǎn)數(shù)printk消息流向/etc/syslog.conf中可配置syslogd的分發(fā)規(guī)那么,例如可以參加: kern.*/tmp/kernel_debug.txt/proc/kernel/printk文件中設(shè)置了一個(gè)優(yōu)先級(jí),高于該優(yōu)先級(jí)的消息才能顯示到控制臺(tái)中模塊許可證聲明模塊許可證聲〔MODULE_LICENSE〕明描述內(nèi)核模塊的許可權(quán)限如果不聲明LICENSE,模塊被加載時(shí),將收到內(nèi)核被污染〔kerneltainted〕的警告編譯內(nèi)核模塊的條件已安裝了GCC工具鏈有一份內(nèi)核源碼,且至少被編譯過(guò)一次。內(nèi)核模塊程序在編譯過(guò)程中要使用內(nèi)核源碼的頭文件〔在include目錄〕和編譯內(nèi)核時(shí)生成的符號(hào)文件。內(nèi)核模塊的編譯可以編寫一個(gè)最簡(jiǎn)單的Makefile:obj-m:=hello.o并采用如下命令編譯:make–C/lib/modules/$(shelluname-r)/buildM=$(shellpwd)modules或采用如下較復(fù)雜的Makefile:ifneq($(KERNELRELEASE),)#callfromkernelbuildsystem obj-m :=hello.oelse KERNELDIR:=/lib/modules/$(shelluname-r)/build PWD:=$(shellpwd)default: make-C$(KERNELDIR)M=$(PWD)modulesendif內(nèi)核模塊的編譯如果我們想由兩個(gè)源文件(比方file1.c和file2.c)構(gòu)造出一個(gè)名稱為module.ko的模塊,那么makefile的obj-m變量可如下編寫:obj-m:=module.omodule-objs:=file1.ofile2.o內(nèi)核模塊的加載與卸載使用insmod命令或modprobe加載模塊:insmod./hello.ko使用rmmod命令卸載模塊:rmmodhello使用lsmod命令查看內(nèi)核中已加載的內(nèi)核模塊的信息通過(guò)查看/proc/modules文件也可查看內(nèi)核中已加載的內(nèi)核模塊的信息。通過(guò)查看/sys/module目錄也可查看內(nèi)核中已加載的內(nèi)核模塊的信息。modprobe會(huì)考慮要裝載的模塊是否引用了一些當(dāng)前內(nèi)核不存在的符號(hào)。如果有這類引用,modprobe會(huì)在當(dāng)前模塊路徑中搜索定義了這些符號(hào)的其他模塊,并同時(shí)將這些模塊也裝載到內(nèi)核。(/lib/modulesmodules.dep/ect/modprob.conf)內(nèi)核模塊參數(shù)module_param〔參數(shù)名,參數(shù)類型,參數(shù)讀/寫權(quán)限〕內(nèi)核支持的模塊參數(shù)類型包括:byte、short、ushort、int、uint、long、ulong、charp(字符指針)、bool。staticchar*whom="world";staticinthowmany=1;module_param(howmany,int,S_IRUGO);module_param(whom,charp,S_IRUGO);裝載模塊指定參數(shù)可通過(guò)insmod或modprobe在裝載模塊時(shí)為其傳入?yún)?shù):

insmodhello_ext.kohowmany=5whom="Students"modprobe也可以從它的配置文件(/etc/modprobe.conf)讀取參數(shù)的值最簡(jiǎn)單的KernelModule…………//export.c

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 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ì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論