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

下載本文檔

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

文檔簡介

Linux內(nèi)核模塊編程主要參考書目《Linux設(shè)備驅(qū)動開發(fā)詳解(第2版)》宋寶華編著人民郵電出版社主要參考書目《Linux設(shè)備驅(qū)動程序(第三版)》魏永明耿岳等譯中國電力出版社主要參考書目《精通Linux驅(qū)動程序開發(fā)》Sreekrishnan編著人民郵電出版社操作系統(tǒng)主要功能:CPU管理存儲管理設(shè)備管理文件管理網(wǎng)絡(luò)與通信管理用戶接口POSIX表示可移植操作系統(tǒng)接口(PortableOperatingSystemInterface)是為解決應(yīng)用程序平臺移植性提出的一種標(biāo)準(zhǔn)。Linux是什么?Linux是一個由幾百萬行源代碼組成的龐大、復(fù)雜的程序,任何人都能從上下載。Linux是一套免費(fèi)的、源代碼開放的、符合POSIX標(biāo)準(zhǔn)標(biāo)準(zhǔn)的操作系統(tǒng)。嚴(yán)格來說,Linux只包含以下圖中內(nèi)核與系統(tǒng)調(diào)用接口那兩層。Linux內(nèi)核的構(gòu)成8Linux的虛擬內(nèi)存管理Linux的虛擬內(nèi)存管理機(jī)制為應(yīng)用程序和驅(qū)動程序提供了兩種效勞:使每個進(jìn)程都擁有自己獨(dú)立的內(nèi)存地址空間;對于32位Linux而言,每個任務(wù)可尋址的內(nèi)存地址空間都為0x00000000~0xFFFFFFFF(232,4GB)當(dāng)物理內(nèi)存不夠4GB時,虛擬內(nèi)存管理模塊會用外存空間模擬內(nèi)存空間,并且該模擬過程對應(yīng)用程序是透明的。9用戶地址空間與內(nèi)核地址空間Linux將每個進(jìn)程的4GB的獨(dú)立地址空間又劃分為用戶地址空間(0x00000000~0xBFFFFFFF)和內(nèi)核地址空間(0xC0000000~0xFFFFFFFF)兩局部。操作系統(tǒng)內(nèi)核代碼和數(shù)據(jù)存放在內(nèi)核地址空間;每個進(jìn)程自己私有的代碼和數(shù)據(jù)存放在用戶地址空間雖然Linux的內(nèi)核代碼和數(shù)據(jù)被映射到了每個進(jìn)程的地址空間中〔所有進(jìn)程看到的內(nèi)容是相同的〕,但在實際的物理內(nèi)存中,只有內(nèi)核代碼和數(shù)據(jù)的一份拷貝。10用戶地址空間與內(nèi)核地址空間虛擬頁物理頁031null213null虛擬頁物理頁021null213null虛擬頁物理頁0null1null213null物理頁taken進(jìn)程id0Nnull1Yos2Y23Y1進(jìn)程1的頁表進(jìn)程id虛擬頁硬盤中的地址進(jìn)程2的頁表進(jìn)程3的頁表內(nèi)頁表外頁表CR3寄存器CPU負(fù)責(zé)查表(虛擬地址->物理地址),查表失敗時觸發(fā)缺頁中斷(14號);OS負(fù)責(zé)填充各個表的內(nèi)容,并提供缺頁中斷的中斷效勞器程序。用戶態(tài)與核心態(tài)一般現(xiàn)代CPU都有幾種不同的指令執(zhí)行級別在高執(zhí)行級別下,代碼可以執(zhí)行特權(quán)指令,訪問任意的物理地址,這種CPU執(zhí)行級別就對應(yīng)著內(nèi)核態(tài)用戶態(tài)指相應(yīng)的低級別執(zhí)行狀態(tài),代碼的掌控范圍會受到限制,只能執(zhí)行CPU指令集的一個子集舉例:intelx86CPU有四種不同的執(zhí)行級別0-3,Linux只使用了其中的0級和3級分別來表示內(nèi)核態(tài)和用戶態(tài)0xc0000000以上的內(nèi)核地址空間只能在內(nèi)核態(tài)下訪問,0x00000000-0xbfffffff的用戶地址空間在兩種狀態(tài)下都可以訪問應(yīng)用程序可以通過Linux系統(tǒng)調(diào)用由用戶態(tài)進(jìn)入內(nèi)核態(tài)Linux進(jìn)程狀態(tài)Linux中任務(wù)和進(jìn)程是相同的術(shù)語,每個進(jìn)程由task_struct結(jié)構(gòu)來描述,即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)核的動態(tài)擴(kuò)展,即在系統(tǒng)運(yùn)行時給內(nèi)核增加新的功能〔即模塊module〕。模塊〔module〕是一段可以被動態(tài)鏈接的目標(biāo)代碼〔.ko〕,它可由insmod命令動態(tài)的裝載并鏈接到正在運(yùn)行的內(nèi)核。鏈接后,它就成了內(nèi)核的一局部,直到用rmmod命令解除鏈接并卸載。Linux驅(qū)動程序就是一種特殊的內(nèi)核模塊。內(nèi)核模塊與應(yīng)用程序的不同內(nèi)核模塊工作在內(nèi)核空間〔supervisorspace〕,而應(yīng)用程序工作在用戶空間〔userspace〕內(nèi)核模塊是一個由多個回調(diào)函數(shù)組成的“被動”代碼集合體,采用了“事件驅(qū)動模型”;而應(yīng)用程序總是從頭至尾的執(zhí)行單個任務(wù)。內(nèi)核模塊不能調(diào)用C標(biāo)準(zhǔn)函數(shù)庫〔glibc庫〕,只能調(diào)用linux內(nèi)核導(dǎo)出的內(nèi)核函數(shù)。內(nèi)核模塊在編程時必須考慮可重入性〔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)出符號EXPORT_SYMBOL(add_integer)可選模塊作者等信息聲明MODULE_AUTHOR(“author_name”)可選最簡單的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ù)通過insmod或modprobe命令加載內(nèi)核模塊時,模塊的加載函數(shù)會自動被內(nèi)核執(zhí)行,完成模塊的相關(guān)初始化工作,通常包括:(1)向內(nèi)核注冊一些數(shù)據(jù)結(jié)構(gòu);〔2〕申請軟硬件資源;〔3〕初始化硬件模塊加載函數(shù)必須用宏“module_init”指定,它返回整型值。假設(shè)初始化成功那么返回0,假設(shè)失敗那么返回一個負(fù)值作為錯誤碼。“__init”和“__exit”都是宏,利用了gcc的擴(kuò)展關(guān)鍵字,分別要求編譯器將所聲明函數(shù)的目標(biāo)代碼放入“init.text”段和“exit.text”段中(兩個特殊的ELF段)。static關(guān)鍵字為了將該函數(shù)名的可見性控制在本文件內(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)最終展開為:staticinitcall_t__initcall_##fn##id__used\__attribute__((__section__(".initcall"level".init")))=fninitcall_t是一個指向函數(shù)的指針類型typedefint(*initcall_t)(void)所以module_init本質(zhì)上是將一個函數(shù)指針變量放在了一名為".initcall6.init"ELF節(jié)中。ExecutableandLinkingFormat模塊卸載函數(shù)模塊卸載函數(shù)必須用宏“module_exit”指定,無返回值。當(dāng)通過rmmod命令卸載某模塊時,模塊的卸載函數(shù)會自動被內(nèi)核執(zhí)行,完成與模塊裝載函數(shù)相反的功能。〔注銷一些內(nèi)核數(shù)據(jù)結(jié)構(gòu),釋放資源等〕。內(nèi)核打印函數(shù)printkprintk〔fmt,args…)級別KERN_EMERG用于緊急消息,常常是那些崩潰前的消息.KERN_ALERT需要立刻動作的情形.KERN_CRIT嚴(yán)重情況,常常與嚴(yán)重的硬件或者軟件失效有關(guān).KERN_ERR用來報告錯誤情況;設(shè)備驅(qū)動常常使用KERN_ERR來報告硬件故障.KERN_WARNING有問題的情況的警告,這些情況自己不會引起系統(tǒng)的嚴(yán)重問題.KERN_NOTICE正常情況,但是仍然值得注意.在這個級別一些平安相關(guān)的情況會報告.KERN_INFO信息型消息.在這個級別,很多驅(qū)動在啟動時打印它們發(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è)置了一個優(yōu)先級,高于該優(yōu)先級的消息才能顯示到控制臺中模塊許可證聲明模塊許可證聲〔MODULE_LICENSE〕明描述內(nèi)核模塊的許可權(quán)限如果不聲明LICENSE,模塊被加載時,將收到內(nèi)核被污染〔kerneltainted〕的警告編譯內(nèi)核模塊的條件已安裝了GCC工具鏈有一份內(nèi)核源碼,且至少被編譯過一次。內(nèi)核模塊程序在編譯過程中要使用內(nèi)核源碼的頭文件〔在include目錄〕和編譯內(nèi)核時生成的符號文件。內(nèi)核模塊的編譯可以編寫一個最簡單的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)核模塊的編譯如果我們想由兩個源文件(比方file1.c和file2.c)構(gòu)造出一個名稱為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)核模塊的信息通過查看/proc/modules文件也可查看內(nèi)核中已加載的內(nèi)核模塊的信息。通過查看/sys/module目錄也可查看內(nèi)核中已加載的內(nèi)核模塊的信息。modprobe會考慮要裝載的模塊是否引用了一些當(dāng)前內(nèi)核不存在的符號。如果有這類引用,modprobe會在當(dāng)前模塊路徑中搜索定義了這些符號的其他模塊,并同時將這些模塊也裝載到內(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ù)可通過insmod或modprobe在裝載模塊時為其傳入?yún)?shù):

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

溫馨提示

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

評論

0/150

提交評論