linux 2.4的動態(tài)模塊是.o結(jié)尾,不是.ko
1.1 example1
#define MODULE
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
MODULE_LICENSE("GPL");
static int __initlkp_init(void)
{
printk("<1>helloworld from the kernel space.. \n");
return 0;
}
static void __exitlkp_cleanup(void)
{
printk("<2>goodbyeworld, leaving kernel space.. \n");
}
module_init(lkp_init);
module_exit(lkp_cleanup);
以上是源代碼,在2.4內(nèi)核中動態(tài)可加載模塊文件開始出一定要有一個MODULE宏定義,不然會出現(xiàn)版本不匹配等錯誤,
宏__init告知編譯程序相關(guān)的函數(shù)和變量只用于初始化,編譯程序?qū)?biāo)有__init的所有代碼存儲到特殊的內(nèi)存中,初始化結(jié)束后就釋放這段內(nèi)存,同樣宏__exit和__exitdata僅用于退出和關(guān)閉例程,
代碼中的最后兩行module_init(lkp_init);module_exit(lkp_cleanup);可以不用加入,但這樣的話模塊在加入和移除時將不會調(diào)用lkp_init, lkp_cleanup,則文件/var/log/message中將不包含提示信息,如果不想使用這種方法,可以使用下面的代碼
1.2 example2
#define MODULE
#include<linux/module.h>
MODULE_LICENSE("MYGPL");
int init_module(void)
{
printk("<1>Hello,world\n");
return 0;
}
void cleanup_module(void)
{
printk("<1>Goodbye cruelworld\n");
}
在此代碼中可以直接將example1中的初始化和退出函數(shù)名字直接改為init_module和cleanup_module,這樣內(nèi)核在加載和移除該模塊時自動調(diào)動初始化和清除函數(shù).
1.3 example3
#define MODULE
#include<linux/kernel.h>
#include<linux/module.h>
MODULE_LICENSE("GPL");
int init_module(void)
{
printk("<1>hello\n");
return 0;
}
voidcleanup_module(void)
{
printk("<1>bye\n");
}
1.4 makefile文件
#Makefile for linuxloadable kernel module
CC=gcc
CFLAG := -I/usr/src/linux-
OBJ=test
$(OBJ).o:$(OBJ).c
-rm $@ -f
$(CC) $(CFLAG) -c $(OBJ).c -o test.o
注意其中的gcc選項一定要包含D_KERNEL__和D__MODULE這兩個選項,不管對于什么的架構(gòu),一定要使gcc在編譯時的環(huán)境版本和運行時的環(huán)境版本相匹配,也即在運行環(huán)境中,假如你使用ARM或者
MODULE_LICENSE("GPL");本句代碼可以不要,但不要的話,運行時會出現(xiàn)"hello:module license 'unspecified' taints kernel.",詞典上對taints的解釋是"感染,污點".
1.5 編譯過程
在命令行輸入make命令編譯生成ELF文件,
insmod hellomod來加載模塊
rmmod hellomod移除hellomod模塊
lsmod查看當(dāng)前已加載模塊
hellomod向模塊發(fā)出的信息可以在/var/log/message文件中查看到,
可用dmesg命令來查看
readelf和ojbdump用于查看目標(biāo)文件的信息