linux内核编程--1模块的装载和卸载
1.???簡(jiǎn)介
linux模塊是具有獨(dú)立功能的程序,它可以被單獨(dú)編譯,但不能獨(dú)立運(yùn)行。它在運(yùn)行時(shí)被鏈接到內(nèi)核作為內(nèi)核的一部分在內(nèi)核空間運(yùn)行,這與運(yùn)行在用戶空間的進(jìn)程是不同的。模塊通常由一組函數(shù)和數(shù)據(jù)結(jié)構(gòu)組成,用來(lái)實(shí)現(xiàn)一種文件系統(tǒng)、一個(gè)驅(qū)動(dòng)程序或其他內(nèi)核上層的功能。
也就是說(shuō):模塊就是整個(gè)內(nèi)核的一部分。但是跟C程序中函數(shù)不一樣的一點(diǎn)是,內(nèi)核模塊可以在它所認(rèn)為適當(dāng)?shù)臅r(shí)候,插入到內(nèi)核或者從內(nèi)核中刪除,而且還不影響內(nèi)核的正常運(yùn)行。從而可以在必要的時(shí)候?qū)?nèi)核進(jìn)行裁剪,這樣能夠更好的適應(yīng)于用戶的需求。
2.???內(nèi)核linux/module.h頭文件
按照前文所述,內(nèi)核linux/module.h頭文件定義了模塊安裝/卸載的相關(guān)函數(shù)和宏定義,以下簡(jiǎn)述幾個(gè)主要的函數(shù)和宏:
1)? module_init()函數(shù)
此函數(shù)以函數(shù)指針為參數(shù),用于注冊(cè)模塊的初始化函數(shù)。相當(dāng)于c程序可以在main函數(shù)之前注冊(cè)初始化函數(shù)。此函數(shù)最終為調(diào)到__define_initcall函數(shù),將函數(shù)指針加入.init段。當(dāng)用insmod命令加載此模塊時(shí),會(huì)調(diào)用此函數(shù)。
#define __define_initcall(fn, id) \ static initcall_t __initcall_##fn##id __used \ __attribute__((__section__(".initcall" #id ".init"))) = fn; \ LTO_REFERENCE_INITCALL(__initcall_##fn##id)2)? module_exit()函數(shù)
此函數(shù)以函數(shù)指針作為參數(shù),用于注冊(cè)模塊的退出(卸載)函數(shù)。相當(dāng)于c程序可以用atexit()注冊(cè)進(jìn)程退出回調(diào)。當(dāng)用rmmod命令卸載模塊時(shí),調(diào)用此函數(shù)。
3)? MODULE_LICENSE/ MODULE_AUTHOR/ MODULE_DESCRIPTION等
此大寫MODULE_開頭的幾個(gè)符號(hào)為定義在linux/module.h頭文件中解釋模塊信息的幾個(gè)宏定義,分別代表:
MODULE_LICENSE--模塊的license,有GPL、BSD等,即模塊遵循的開源協(xié)議;
MODULE_AUTHOR--模塊作者
MODULE_DESCRIPTION--模塊描述
3.???模塊代碼
以老掉牙的hello world為例,編碼如下模塊代碼如下,假設(shè)命令為:module_test.c。其中,printk函數(shù)為內(nèi)核日志輸出函數(shù),可以打印內(nèi)核日志信息。
//必要的頭文件 #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> //模塊許可證聲明(必須) MODULE_LICENSE("Dual BSD/GPL"); //模塊加載函數(shù)(必須) static int hello_init(void) { printk(KERN_ALERT "Hello World enter/n"); return 0; } //模塊卸載函數(shù)(必須) static void hello_exit(void) { printk(KERN_ALERT "Hello World exit/n"); return; } //模塊的注冊(cè) module_init(hello_init); module_exit(hello_exit); //聲明模塊的作者(可選) MODULE_AUTHOR("XXX"); //聲明模塊的描述(可選) MODULE_DESCRIPTION("This is a simple example!/n"); //聲明模塊的別名(可選) MODULE_ALIAS("A simplest example");4.???模塊編譯
編寫完模塊代碼后,我們需要對(duì)其進(jìn)行相關(guān)操作,變成一個(gè)內(nèi)核模塊文件(.ko文件)。也就需要寫個(gè)Makefile文件,編譯剛才的模塊的代碼。
obj-m += kernel_test.o #generate the path CURRENT_PATH:=$(shell pwd)#the current kernel version number LINUX_KERNEL:=$(shell uname -r) #the absolute path--根據(jù)獲取的內(nèi)核版本拼裝絕對(duì)路徑 LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL) #complie object all: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules #clean clean: make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean當(dāng)make的目標(biāo)為all時(shí),-C $(KDIR) 指明跳轉(zhuǎn)到內(nèi)核源碼目錄下讀取那里的Makefile;M=$(PWD) 表明然后返回到當(dāng)前目錄繼續(xù)讀入、執(zhí)行當(dāng)前的Makefile。
注意點(diǎn):
1)??????Makefile文件命名為:Makefile,第一個(gè)字符大寫;
2)??????Makefile文件與源代碼(.c)放在同級(jí)目錄;
3)??????以root權(quán)限執(zhí)行make命令----root用戶或普通用戶+sudo。
5.???測(cè)試驗(yàn)證---裝載/卸載模塊
Linux提供insmod命令裝載內(nèi)核模塊,rmmod命令卸載內(nèi)核模塊,相關(guān)的還有modinfo(顯示模塊的信息:模塊作者、模塊license等),lsmod(列出系統(tǒng)所有內(nèi)核模塊)。以下就測(cè)試模塊的裝載/卸載過(guò)程中printk打印的消息----用dmesg命令查看。-------------我的打印消息是:” Linux cai ji.------start----”、 “Linux caiji.------end”
6.???參考鏈接
http://blog.csdn.net/chang198932/article/details/17006537
總結(jié)
以上是生活随笔為你收集整理的linux内核编程--1模块的装载和卸载的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: UI行业发展预测 系列规划的调整
- 下一篇: linux下的启停脚本