參考用書:《操作系統(tǒng)實踐:基于Linux的應(yīng)用與內(nèi)核編程》
一.添加一個內(nèi)核模塊
1.1需求分析
對于一個應(yīng)用程序而言,源代碼經(jīng)編譯后與標準運行庫鏈接,通過系統(tǒng)調(diào)用執(zhí)行操作系統(tǒng)內(nèi)核中的特權(quán)指令,指令返回的結(jié)果通過系統(tǒng)調(diào)用返回給用戶,完成程序。
由于Linux是單內(nèi)核多模塊的操作系統(tǒng),整個操作系統(tǒng)只包含一個由多個不同功能模塊組成的內(nèi)核,通過Linux系統(tǒng)的這種特性,可以動態(tài)添加自己編寫的內(nèi)核模塊,并由系統(tǒng)每次啟動時進行加載。
通過內(nèi)核模塊的動態(tài)添加和刪除,可以直觀的感受到內(nèi)核模塊的編寫以及動態(tài)添加和刪除的過程??梢酝ㄟ^此次實驗理解用戶態(tài)(User Model)和內(nèi)核態(tài)(Kernel Model)的關(guān)系。并掌握內(nèi)核模塊代碼中的一些常見宏和參數(shù)以及內(nèi)核模塊程序和應(yīng)用程序的差異。
實驗流程為:編寫kello.c文件和Makefile文件,并使用insmod和rmmmod命令對內(nèi)核模塊進行安裝和卸載。觀察終端輸出的不同信息。同時編寫代碼時應(yīng)注意安全問題,不要對內(nèi)核進行不當訪問從而使系統(tǒng)出現(xiàn)錯誤。
輸入:使用insmod安裝所編寫的內(nèi)核模塊。
輸出:通過dmesg命令觀察安裝內(nèi)核模塊和卸載內(nèi)核模塊所輸出的信息。
1.2概要設(shè)計
本次實驗包含兩個文件:kello.c和編譯所需的Makefile文件,kello.c文件包含模塊初始化函數(shù)hello_init,在模塊初始化時被調(diào)用,以及模塊回收函數(shù)hello_exit,在模塊被撤銷時使用。
在該文件的最后,需要添加兩行聲明module_init(hello_init)和module_exit(hello_exit),使模塊被更高效的加載執(zhí)行和撤銷,加快內(nèi)存的分配和回收
對于Makefile文件內(nèi)容,KERNELRELEASE定義在linux內(nèi)核源代碼中的頂層makefile,boj-m表示所安裝內(nèi)核模塊的名稱,需要和c文件名字相同。
KDIR和PWD目錄分別代表內(nèi)核的源代碼目錄和當前的工作路徑,defult中為編譯命令以及一些文件的刪除命令。
1.3詳細設(shè)計
Kello.c的hello_init調(diào)用printk輸出一段初始化信息,hello_exit調(diào)用printk輸出模塊回收時打印的信息。
對于Makefile文件,KERNELRELEASE是在Linux內(nèi)核源代碼頂層Makelile中定義的一個變量,在第一次讀取執(zhí)行此 Makefile文件時,KERNELRELEASE沒有被定義,所以make將讀取執(zhí)行else之后的內(nèi)容。
如果make的目標是clean. 直接執(zhí)行clean操作,然后結(jié)束。
當沒有聲明make的目標時,make執(zhí)行默認操作,即default 后的指令,此時-C$ (KDIR)指明跳轉(zhuǎn)到內(nèi)核源代碼目錄下讀取那里的Makefiles SUBDIRS $ (PWD) 表明需要返回到當前目錄繼續(xù)讀入并執(zhí)行當前的Makefile.當從內(nèi)核源代碼目錄返回時, KERNELRELEASE已被定義,kbuild也被啟動去解析kbuild語法的語句,make將繼續(xù)讀取else之前的內(nèi)容。
實驗過程:
在當前文件夾下執(zhí)行make命令

觀察當前文件夾是否生成所需文件

sudo insmod 安裝LKM

觀察安裝LKM后dmesg輸出的內(nèi)核初始化信息

sudo rmmod 卸載LKM

觀察卸載LKM后dmesg輸出的內(nèi)核初始化和撤銷信息

1.4調(diào)試分析
分析一:make命令提示空變量名錯誤

首先遇到的錯誤為,make命令報告空變量名。是make文件的格式問題,注意在$(MAKE) -C $(KDIR) SUBDIRS =$(shell pwd) modules,SUBDIRS的后沒有空格,去掉空格后問題解決。
分析二:mkdir創(chuàng)建目錄權(quán)限不夠


mkdir創(chuàng)建目錄權(quán)限不夠,錯誤定位在fixdep.c文件的404行,fatal error打開依賴文件的權(quán)限不夠,并顯示compilation terminated(編譯結(jié)束)。
fixdep.c文件是make的一個工具,由make在編譯時調(diào)用。問題出在make -C SUBDIRS=處,應(yīng)修改為make -C M=。二者的區(qū)別在于,$(MAKE)相當于make,-C 選項的作用是指將當前工作目錄轉(zhuǎn)移到所指定的位置。“M=”表示當用戶需要以某個內(nèi)核為基礎(chǔ)編譯一個外部模塊的話,需要在make modules 命令中加入“M=dir”,程序會到所指定的dir目錄中查找模塊源碼,將其編譯,生成.ko文件。
M并非隨意命名,在新的內(nèi)核模塊編程中的make命令中有個M選項,是makefile腳本中的一個變量,$(MAKE) -C $(KDIR) M=$(PWD)與$(MAKE) -C $(KDIR) SUBDIRS =$(PWD)的作用是一樣的,不過SUBDIRS是過時的使用方法,修改后問題得以解決。文章來源:http://www.zghlxwxcb.cn/news/detail-744832.html

make文件和c文件如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-744832.html
ifneq ($(KERNELRELEASE),)
obj-m := kello.o
else
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) M=$(shell pwd) modules
rm -r -f .tmp_versions *.mod.c .*.cmd *.o *.symvers
endif
#include<linux/module.h>
/*
此函數(shù)為模塊初始化實例,
將在模塊初始化時被調(diào)用
*/
int hello_init(void)
{
printk("\nI AM HERE IN KERNEL:)\n");
return 0;
}
/*
此函數(shù)為模塊回收實例,
將在模塊被撤銷時使用
*/
void hello_exit(void){
printk("\n I AM OUT BYE BYE :)\n");
}
MODULE_AUTHOR("zhuoge04");//描述模塊作者為本人
MODULE_LICENSE("GPL");
/*
以下兩行聲明可以使模塊被更高效的加載執(zhí)行和撤銷,
加快內(nèi)存的分配和回收
*/
module_init(hello_init);
module_exit(hello_exit);
到了這里,關(guān)于操作系統(tǒng)實驗-添加一個內(nèi)核模塊的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!