Hello,Kernel!

2010年9月13日 由 edsionte 留言 »

学习内核模块编程,第一个小程序当然是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。

广告位

56 条评论

  1. edsionte说道:

    @explore, list的回复在你邮箱。

    [回复一下]

  2. explore说道:

    我想问一下,楼上khedive的问题解决来不?

    [回复一下]

  3. explore说道:

    终于是把这个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 回复:

    @explore, 是我的疏忽,头文件处的空格是博客插件显示的问题导致的,给大家带来麻烦了!
    内核模块的打印信息不是直接显示在当前终端下的,需要用dmesg命令查看或者直接
    查看/var/log/syslog文件。

    [回复一下]

  4. gududesiling说道:

    edsionte,你好,很想看你写的文章,很精辟,有些东西比网上很多地方解释的都清楚,不过我有一个疑问,怎么没有见到你2011年的文章呢?是不是不再写文章了,还是因为工作,有些东西不能写了,还是博客换地方了,能声明一下么?说实在话的,我也写博客,但是很多都是摘抄别人的,我也希望能把自己好的东西让别人分享,这样我也很快乐。。。我很想和你成为一个技术好友,可惜我实力不够,只能瞻仰了。。。。

    [回复一下]

    edsionte 回复:

    @gududesiling, 这位朋友,你好,首先很感谢您对我以及本博客的支持。本人目前正在读研一,我的学习是随着导师的项目进行的。上学期主要研究内核,目前正在作其他项目,所以关于内核的文章就少了。不过本人研究生阶段的方向仍然是内核。所以有什么问题你可以在博客提问。再次感谢你。

    [回复一下]

  5. jane说道:

    非常羡慕你选择了一个自己喜欢的方向,我已经研究生毕业工作了两年了,也对内核挺感兴趣的,但是还算是个菜鸟。谢谢你写的文章,加油!

    [回复一下]

    edsionte 回复:

    @jane, 我接触内核也一年多一点。坚持就是胜利。

    [回复一下]

  6. arnk说道:

    你这个是在ubuntu下做的实验吧!有些系统比如gentoo,LINUX_KERNEL_PATH定义成/usr/src/linux就可以了。不需要像ubuntu那样要安装linux headers

    [回复一下]

    edsionte 回复:

    @arnk, 这个是在ubuntu下实验的。本文末尾有注明。

    [回复一下]

  7. sticwin说道:

    你好,我按照上面所说的操作,提示的是make:*** No targets. stop.
    请问哪里出错了,我把代码发到了你的邮箱中了

    [回复一下]

    edsionte 回复:

    @sticwin, 一般这种提示就是makefile有问题,请仔细检查你的makefile

    [回复一下]

    keroro 回复:

    @sticwin, 我也有这样的错误,看了一下,是我在hello.c里的模块许可声明前面加了“#”。。还有有一处说明没注释掉也出现了这个错误。

    [回复一下]

  8. gwq说道:

    编写makefile文件那部分看不懂,难道要学了编译原理才能看懂的??
    请教一下

    [回复一下]

    edsionte 回复:

    @gwq, 看看make和makefile的资料吧。官方资料:http://www.gnu.org/software/make/manual/make.html#Overview

    [回复一下]

  9. liangzhukun说道:

    朋友,非常感谢你带路,谢谢了。前面的风景一定会很美丽!

    [回复一下]

  10. liangzhukun说道:

    朋友,您好。我是通过陈莉君老师的书认识西安邮电大学Linux Kernel兴趣小组的,非常感谢你们共享您们的学习和研究成果,我周围的很多同学受益匪浅。希望您们的发展越来越好。

    [回复一下]

    edsionte 回复:

    @liangzhukun, 谢谢您,这里是我的个人博客,希望为您能够提供帮助。小组的网站:xiyoulinux.org

    [回复一下]

  11. liangzhukun说道:

    ^_^.Best Wishes

    [回复一下]

  12. leeyongchao说道:

    师兄好啊,你现在在搞什么东东啊?

    [回复一下]

发表回复

windows 7 ultimate product key

windows 7 ultimate product key

winrar download free

winrar download free

winzip registration code

winzip registration code

winzip free download

winzip free download

winzip activation code

winzip activation code

windows 7 key generator

windows 7 key generator

winzip freeware

winzip freeware

winzip free download full version

winzip free download full version

free winrar download

free winrar download

free winrar

free winrar

windows 7 crack

windows 7 crack

windows xp product key

windows xp product key

windows 7 activation crack

windows7 activation crack

free winzip

free winzip

winrar free download

winrar free download

winrar free

winrar free

download winrar free

download winrar free

windows 7 product key

windows 7 product key