編譯一個自己的內核模塊,并加載進內核
本文檔的Copyleft歸rosetta所有,使用GPL發布,可以自由拷貝、轉載,轉載時請保持文檔的完整性。
參考資料:《Linux設備驅動程序 第三版》
來源:http://blog.csdn.net/rosetta/article/details/7563601
以前也曾經想過往Linux內核編程方向長展,但總歸是沒有入門的機會,看過《Linux設備驅動程序》(買來已經兩年多了),但就像看天書似的。
現在往網絡編程方面發展,涉及面還是挺廣的,這也是一次偶然的機會,上頭讓我把Ipsec的算法模塊整理下,雖然這工作做起來非常無聊,但還是讓我發現了和設備驅動相關的東西,讓我的精神為之一振,從而再次拿起《Linux設備驅動程序》來為我答疑。
最近還在看openswan klips的實現,涉及到網卡驅動程序編寫,慢慢都給整理成筆記,今天先把這最基本的基礎知識先帖上。
知識點:
1. 編譯多個.c源文件的ko(單個文件編寫網上有太多的教程,多個c源文件編譯是這我這回遇到的)
2. 編寫帶參數的內核模塊(這個順便也給記下,雖然貌似沒有用到)
3. insmod,rmmod,mknod,modprobe,dmesg等命令使用(dmesg比較有用,有些人不知道用這個命令,就說要用串口顯示信息,其實dmesg命令更方便,-c選項清空信息)
4. 無法插入內核的原因。(這個也是關鍵,很多時候操作起來比較簡單,比如編譯內核源碼,但可能會碰到一系列錯誤,解決一堆錯誤最能提升一個人的能力)
一、編譯多個.c文件的ko模塊并插入內核
//test_module.c
#include
#include
#include "extern_app.h"
static char *who = "linux ss";
static int many = 1;
module_param(many, int, S_IRUGO);
module_param(who, charp, S_IRUGO);
static int __init hello_init(void)
{
test();
static int i = 0;
for(i = 0; i < many; i++)
printk(KERN_ALERT "Hello, %s!\n", who);
return 0;
}
static void __exit hello_exit(void)
{
printk(KERN_ALERT "Goodbye\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
//extern_app.c
#include
#include
int test(void)
{
printk("test here.\n");
return 0;
}
//extern_app.h
#ifndef __EXTERN_APP_H
#define __EXTERN_APP_H
extern int test(void);
#endif
//Makefile
#ifneq ($(KERNELRELEASE),)
obj-m := my_module.o
my_module-objs := test_module.o extern_app.o
#else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
rm -rf Module.* modules.*
.PHONY: default clean
#endif
make,如果執行成功則生成my_module.ko
//執行insmod 后并調用dmesg,正常情況如下顯示:
[root@localhost module_kernel]# insmod my_module.ko who=Coding many=5
[root@localhost module_kernel]# dmesg
test here.
Hello, Coding!
Hello, Coding!
Hello, Coding!
Hello, Coding!
Hello, Coding!
[root@localhost module_kernel]#
//rmmod從內核移除模塊
[root@localhost module_kernel]# insmod my_module.ko
insmod: error inserting 'my_module.ko': -1 File exists
[root@localhost module_kernel]# rmmod my_module
二、出錯原因解決方法
在插入模塊時常遇到的錯誤:
[root@panlimin module_study]# insmod my_module.ko
insmod: error inserting 'my_module.ko': -1 Invalid module format
dmesg查看內核報錯消息:
[root@panlimin module_study]# dmesg
my_module: no symbol version for module_layout
[root@panlimin module_study]#
一般出這個錯在make時會有類似這樣的警告:
WARNING: Symbol version dump /root/study/kernel/linux-2.6.34/Module.symvers
is missing; modules will have no dependencies and modversions.
這是應該Linux內核版本依賴出現了問題,這種情況一般出現在自行編譯內核后沒有鏈接到正確的內核源碼目錄樹情況,或者
內核目錄樹頂層的Module.symvers文件丟失。因為模塊代碼必須針對要鏈接的內核版本重新編譯。
如果沒有此警告,但在insmod時還是報此錯誤,就需要查看Module.symvers文件是否正確,比如這個文件可能是0字節,
Module.symvers在編譯內核時會生成,如果發行版本在/lib/module/目錄下對應的內核目錄樹中會有,此時只要確保該文件正確
再重新make,insmod應該就沒問題了。
除了insmod可以將模塊插入內核外,modprobe也可以,它們的區別在于后者會考慮要插入的模塊是否引用了一些當前內核不存在的符號,
如果有這類引用,modprobe會在查找相應模塊并嘗試插入到內核。所以有時使用insmod插入無效時還可以使用modprobe.
如果由于模塊依賴導致符號表出現問題,比如,~/.viminfo被破壞,甚至無法加載網絡接口等,可以在/lib/module/對應的內核目錄下
執行depmod -a重新生成正確的符號表,執行過程需要點時間。
*博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。