相信很多做过内核编程的人都写过makefile,虽然之前写过一些简单的内核模块写过makefile,到今天想要写一个内核模块的时候发现之前学的的已经全部忘记了。言归正传,Makefile这个文件还是真的不好写。相信你跟我一样之前编程的时候为了图好看的代码风格,敲了很多很多的空格,基本上逢符号必空格。今天在写makefile时候,写完了,一make,各种错误弹出来。顿时知道真相的我眼泪掉下来,而且这个错误还跟我们写c程序错误不一样,基本上都是一些什么什么文件错误,什么什么文件不存在了。
先贴出来我的makefile。
#makefile file
obj-m := kernelhello.o
CURRENT_PATH:=$(shell pwd)
LINUX_KERNEL:=$(shell uname -r)
LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)
all:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean
再看看我的.c文件
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
static int __init lkp_init(void)
{
printk("<1>hello world! from the kernel space...\n");
return 0;
}
static void __exit lkp_cleanup( void )
{
printk("<2>Goodbye world! from the kernel space...\n");
}
module_init(lkp_init);
module_exit(lkp_cleanup);
MODULE_LICENSE("GPL");
~
make以后:
经过多方查找资料,得出的结论就是M=XXX的=号后边不要写空格不要写空格不要写空格(重要的事说三边)!M前面一定要打上空格,因为M之前是linux kernel的绝对路径,如果没有空格的话系统会直接把等号前面都看成是kernel的绝对路径(而实际上的绝对路径是比这个少一个最后的M字母的),of couse这个路径是错误的,没办法找到的。
如果 obj-m := kernelhello.o中的obj-m的-两端写上了空格,则make完了以后只有 modules.order Module.symvers这两个文件,其他的没有。
最后终于make出来了一个kernelhello.ko文件,(从这里开始操作都要是超级用户)用insmod kernelhello.ko命令插入模块,用lsmod命令可以查找模块是否已经插入到内核中去。最后用dmesg打印出buffer中的信息,最后一行就可以看见自己写的hello。移除模块的命令是rmmod kernelhello。
模块常用的宏:
MODULE_AUTHOR(“”); 模块作者
MODULE_DESCRIPTION(“”); 模块描述
MODULE_ALIAS(“”); 模块别名
__init和__exit是属性 —— 联结到函数(或者变量)的元数据片。属性在用户空间的C代码中是很罕见的,但是内核中却很普遍。所有标记为__init的,会在初始化后释放内存以供重用(还记得那条过去内核的那条“Freeing unused kernel memory…[释放未使用的内核内存……]”信息吗?)。__exit表明,当代码被静态构建进内核时,该函数可以安全地优化了,不需要清理收尾。
Linux的通用makefile模板:http://www.linuxdiyf.com/linux/7985.html
Linux下面系统开发Makefile须知:http://www.linuxdiyf.com/linux/1237.html
Ubuntu下编译的第一个内核模块:http://www.linuxdiyf.com/linux/8331.html
查找Linux内核模块具体信息:http://www.linuxdiyf.com/linux/9115.html
Linux内核模块配置文件:http://www.linuxdiyf.com/linux/8859.html