学习内核模块编程,第一个小程序当然是hello,kernel!了,这应当算是一个惯例了。以前大三的时候在实验课上做过模块编程,记得当时还是许师兄带我们的实验,不过现在又忘了。晚上试了试,很快就运行成功了,不过还是出现了一些问题。现在将我的步骤记录如下,供和我一样的初学者学习。
1.首先编写hello.c文件
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> //必选 //模块许可声明 MODULE_LICENSE("GPL"); //模块加载函数 static int hello_init(void) { printk(KERN_ALERT "hello,I am edsionte\n"); return 0; } //模块卸载函数 static void hello_exit(void) { printk(KERN_ALERT "goodbye,kernel\n"); } //模块注册 module_init(hello_init); module_exit(hello_exit); //可选 MODULE_AUTHOR("edsionte Wu"); MODULE_DESCRIPTION("This is a simple example!\n"); MODULE_ALIAS("A simplest example");
通常一个模块程序的中,模块加载函数,模块卸载函数以及模块许可声明是必须有的,而象模块参数,模块导出符号以及模块作者信息声明等都是可选的。
我们编写了模块加载函数后,还必须用module_init(mode_name);的形式注册这个函数。因为当我们接下来用insmod加载模块时,内核会自动去寻找并执行内核加载函数,完成一些初始化工作。类似的当我们使用rmmod命令时,内核会自动去执行内核卸载函数。
请注意这里的printk函数,可以简单的理解为它是内核中的printf函数,初次使用很容易将其打成printf。
2.编写Makefile文件
记得大三,那时候实验课上接触到Makefile,只是按照书上的内容敲上去。不过有了上一周对Makefile相关语法的了解,现在看起来已经基本知道为什么要这么写了。那么下面我们看Makefile文件。
obj-m += hello.o #generate the path CURRENT_PATH:=$(shell pwd) #the current kernel version number LINUX_KERNEL:=$(shell uname -r) #the absolute path 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
首先第一句话指定要被编译的文件。其实Makefile中有这样一句话就可以了,但是这样的话每次make时都要加入其他命令,所以我们不妨就在Make中加入每次要执行的命令(脚本语言的功能体现出来了)。每次只要输入make命令即可。
我们首先获得当前的相对路径(你可以在终端输入pwd试一下这个命令),然后再获得当前内核的版本号,这样就可以直接获得当前内核的绝对路径。当然你可以直接输入当前内核版本,不过这样不方便移植,如果当前内核版本号与此文件中的版本号不同时,就得修改。所以上面的方法有很好的移植性,而且可读性也强。
这里会经常出现$(variable name)这样的字符串,其实这是对括号内变量的一种引用,具体可参考Makefile的相关语法规则。
3.make
完成上述两个文件后,在当前目录下运行make命令,就会生成hello.ko文件,即模块目标文件。
4.insmod,rmmod和dmesg
insmod命令可以使我们写的这个模块加入到内核中,但是一般我们要加上sudo。rmmod当然就是卸载这个模块了。我们在加载或卸载模块时都有一些提示语,即我们printk中显示的语句,这时候可以用dmesg命令来查看。
ok,第一个模块编程就这么简单,try一下!
Update 2011/04/03
本文所描述的程序在ubuntu系统下测试成功。其他的Linux发行版应适当修改源码目录,即修改LINUX_KERNEL_PATH。
@explore, list的回复在你邮箱。
[回复一下]
我想问一下,楼上khedive的问题解决来不?
[回复一下]
终于是把这个hello.c调试成功了。看了N个网页(N>100),最后从http://www.360doc.com/content/10/1207/13/1378815_75806990.shtml得到启示找到了问题所在,解决来楼上khedive的问题:
make -C /usr/src/kernels/2.6.35.12-88.fc14.i686 M=/root/projects/hello modules
make[1]: Entering directory `/usr/src/kernels/2.6.35.12-88.fc14.i686′
CC [M] /root/projects/hello/hello.o
/root/projects/hello/hello.c:2:28: fatal error: linux/module.h : No such file or directory
compilation terminated.
make[2]: *** [/root/projects/hello/hello.o] Error 1
make[1]: *** [_module_/root/projects/hello] Error 2
make[1]: Leaving directory `/usr/src/kernels/2.6.35.12-88.fc14.i686′
make: *** [all] Error 2
原因:在于原文hello.c的3个头文件,
01 #include
02 #include
03 #include
尖括号内多来两个空格,导致文件找不到。
把空格去掉后,在我的机器上成功的得到来hello.ko等文件。但是在执行insmod hello.ko(在root用户下)并不能打印出内容,但是用dmesg命令可以查看到。到底这里的头文件空格问题是否合法呢?在哪些平台下是合法的呢?还是楼主手误,这里必须打个问号!
[回复一下]
edsionte 回复:
5月 7th, 2011 at 16:12
@explore, 是我的疏忽,头文件处的空格是博客插件显示的问题导致的,给大家带来麻烦了!
内核模块的打印信息不是直接显示在当前终端下的,需要用dmesg命令查看或者直接
查看/var/log/syslog文件。
[回复一下]
edsionte,你好,很想看你写的文章,很精辟,有些东西比网上很多地方解释的都清楚,不过我有一个疑问,怎么没有见到你2011年的文章呢?是不是不再写文章了,还是因为工作,有些东西不能写了,还是博客换地方了,能声明一下么?说实在话的,我也写博客,但是很多都是摘抄别人的,我也希望能把自己好的东西让别人分享,这样我也很快乐。。。我很想和你成为一个技术好友,可惜我实力不够,只能瞻仰了。。。。
[回复一下]
edsionte 回复:
5月 8th, 2011 at 20:54
@gududesiling, 这位朋友,你好,首先很感谢您对我以及本博客的支持。本人目前正在读研一,我的学习是随着导师的项目进行的。上学期主要研究内核,目前正在作其他项目,所以关于内核的文章就少了。不过本人研究生阶段的方向仍然是内核。所以有什么问题你可以在博客提问。再次感谢你。
[回复一下]
非常羡慕你选择了一个自己喜欢的方向,我已经研究生毕业工作了两年了,也对内核挺感兴趣的,但是还算是个菜鸟。谢谢你写的文章,加油!
[回复一下]
edsionte 回复:
6月 29th, 2011 at 20:43
@jane, 我接触内核也一年多一点。坚持就是胜利。
[回复一下]
你这个是在ubuntu下做的实验吧!有些系统比如gentoo,LINUX_KERNEL_PATH定义成/usr/src/linux就可以了。不需要像ubuntu那样要安装linux headers
[回复一下]
edsionte 回复:
11月 1st, 2011 at 12:04
@arnk, 这个是在ubuntu下实验的。本文末尾有注明。
[回复一下]
你好,我按照上面所说的操作,提示的是make:*** No targets. stop.
请问哪里出错了,我把代码发到了你的邮箱中了
[回复一下]
edsionte 回复:
3月 1st, 2012 at 09:45
@sticwin, 一般这种提示就是makefile有问题,请仔细检查你的makefile
[回复一下]
keroro 回复:
7月 25th, 2012 at 10:46
@sticwin, 我也有这样的错误,看了一下,是我在hello.c里的模块许可声明前面加了“#”。。还有有一处说明没注释掉也出现了这个错误。
[回复一下]
编写makefile文件那部分看不懂,难道要学了编译原理才能看懂的??
请教一下
[回复一下]
edsionte 回复:
9月 19th, 2012 at 09:36
@gwq, 看看make和makefile的资料吧。官方资料:http://www.gnu.org/software/make/manual/make.html#Overview
[回复一下]
朋友,非常感谢你带路,谢谢了。前面的风景一定会很美丽!
[回复一下]
朋友,您好。我是通过陈莉君老师的书认识西安邮电大学Linux Kernel兴趣小组的,非常感谢你们共享您们的学习和研究成果,我周围的很多同学受益匪浅。希望您们的发展越来越好。
[回复一下]
edsionte 回复:
9月 20th, 2012 at 11:10
@liangzhukun, 谢谢您,这里是我的个人博客,希望为您能够提供帮助。小组的网站:xiyoulinux.org
[回复一下]
^_^.Best Wishes
[回复一下]
师兄好啊,你现在在搞什么东东啊?
[回复一下]