简单实例讲解linux的module模块编译步骤
(2014-10-24 10:19:17)
标签:
modulelinux |
分类: Linux/Unix |
本文将直接了当的带你进入linux的模块编译。当然在介绍的过程当中,我也会添加一些必要的注释,以便初学者能够看懂。之所以要写这篇文章,主要是因为从书本上学的话,可能要花更长的时间才能学会整个过程,因为看书的话是一个学习过程,而我这篇文章更像是一个培训。所以实践性和总结性更强。通过本文你将会学到编译一个模块和模块makefile的基本知识。以及加载(卸载)模块,查看系统消息的一些知识;
声明:本文为初学者所写,如果你已经是一个linux模块编译高手,还请指正我文章中的错误和不足,谢谢
第一步:准备源代码
首先我们还是要来编写一个符合linux格式的模块文件,这样我们才能开始我们的模块编译。假设我们有一个源文件mymod.c。它的源码如下:
mymod.c
-
#include
-
#include
-
#include
-
MODULE_AUTHOR("Yu
Qiang" ); -
MODULE_LICENSE("GPL");
-
static
int nbr = 10; -
module_param(nbr,
int, S_IRUGO); -
-
static
int __init void)yuer_init( -
{
-
int i; -
for(i=0; i -
{ -
printk(KERN_ALERT "Hello, How ,are you. %d\n" i); -
} -
return 0; -
}
-
-
static
void __exit void)yuer_exit( -
{
-
printk(KERN_ALERT"I come );from yuer's module, I have been unlad.\n" -
}
-
module_init(yuer_init);
-
module_exit(yuer_exit);
我们的源文件就准备的差不多了,这就是一个linux下的模块的基本结构。第9行是导出我们的符号变量nbr。这样在你加载这个模块的时候可以动态修改这个变量的值。稍后将演示。yuer_init()函数将在模块加载的时候运行,通过输出的结果可以看到我们的模块是否加载成功。
第二步:编写Makefile文件
首先还是来看看我们Makefile的源文件,然后我们再来解释;
Makefile
obj-m := modules.o
modules-objs:=
KDIR := /lib/modules/`uname -r`/build
PWD := $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o .* .cmd *.ko *.mod.c .tmp_versions
现在我来说明一下这个Makefile。请记住是大写的Makefile而不是小写的makefile;
obj-m :这个变量是指定你要声称哪些模块模块的格式为 obj-m := <模块名>.o
modules-objs :这个变量是说明声称模块modules需要的目标文件 格式要求
KDIR
M=
PWD
第三步:编译模块
现在我们已经准备好了我们所需要的源文件和相应的Makefile。我们现在就可以编译了。在终端进入源文件目录输入make
运行结果:
-
make[1]:
Entering 2.6.24-24-generic'directory `/usr/src/linux-headers- -
CC
[M] /home/yuqiang/桌面/mymodule/mymodules.o -
LD
[M] /home/yuqiang/桌面/mymodule/modules.o -
Building
modules, stage 2. -
MODPOST
1 modules -
CC
/home/yuqiang/桌面/mymodule/modules.mod.o -
LD
[M] /home/yuqiang/桌面/mymodule/modules.ko -
make[1]:
Leaving 2.6.24-24-generic'directory `/usr/src/linux-headers-
第四步:加载/卸载我们的模块
从上面的编译中我可以看到。已经有一个modules.ko生成了。这就是我们的模块了。现在我们就可以来加载了。
首先在终端输入:sudo insmod modules.ko
现在我们来看看我们的模块加载成功没有呢?
在终端输入:dmesg | tail -12
显示结果如下:
-
[17945.024417]
sd 9:0:0:0: Attached scsi generic sg2 type 0 -
[18046.790019]
usb 5-8: USB disconnect, address 9 -
[19934.224812]
Hello, How are you. 0 -
[19934.224817]
Hello, How are you. 1 -
[19934.224818]
Hello, How are you. 2 -
[19934.224820]
Hello, How are you. 3 -
[19934.224821]
Hello, How are you. 4 -
[19934.224822]
Hello, How are you. 5 -
[19934.224824]
Hello, How are you. 6 -
[19934.224825]
Hello, How are you. 7 -
[19934.224826]
Hello, How are you. 8 -
[19934.224828]
Hello, How are you. 9
看到了吧。我们的模块的初始化函数yuer_init();已经成功运行了。说明我们的模块已经加载成功;
现在我们再来卸载模块试试看。
在终端输入:sudo rmmod modules
在终端输入:dmesg | tail -3
-
[19934.224826]
Hello, How are you. 8 -
[19934.224828]
Hello, How are you. 9 -
[20412.046932]
I come from yuer's module, I have been unlad.
可以从打印的信息中看到,我们的模块的退出函数已经被执行了。说明我们的模块已经被成功的卸载了。到目前位置我们就已经算是对模块的编译到编译运行算是有了一个整体上的认识了。对于以后深入的学习还是应该有点帮助的。下面我们将在看看于模块相关的一些简单的操作。
第五步:加载模块时传递参数
在终端输入:sudo insmod module_name.ko nbr=4
在终端输入:dmesg | tail -6
显示结果如下:
-
[20800.655694]
Hello, How are you. 9 -
[21318.675593]
I come from onefile module, I have been unlad. -
[21334.425373]
Hello, How are you. 0 -
[21334.425378]
Hello, How are you. 1 -
[21334.425380]
Hello, How are you. 2 -
[21334.425381]
Hello, How are you. 3
这样我们就可以看到在模块加载的时候动态设置了我们的一个变量。初始化函数中的循环只执行了4次。
可能你会问我怎么知道一个模块可以设置那些变量呢。当然,你可以先不设变量加载一次。然后可以在终端输入ls /sys/module//parameters/来查看。在这里我们是这样输入的
在终端输入:ls /sys/moedle/modules/parameters/
显示结果:
nbr
如果我们的模块加载成功了。最后我们还可以通过modinfo来查看我们的模块信息。如下
在终端输入:sudo modinfo modules.ko
-
filename:
modules.ko -
license:
GPL -
author:
Yu Qiang -
srcversion:
20E9C3C4E02D130E6E92533 -
depends:
-
vermagic:
2.6.24-24-generic SMP mod_unload 586 -
parm:
nbr:int
本文总结:
在写到MODULE_AUTHOR("Yu Qiang")的时候,你应该想到还有
在写到module_param(nbr, int, S_IRUGO);的时候,你应该想到还有
...
在用到insmod 和 modinfo的时候。你应该想到还有
...
http://hi.baidu.com/20065562/blog/item/1f918825f767df0b4d088dcf