第四篇:一个简单模块测试
日期 2009-3-8
代码抄的是阿南的教程少的呵呵
#define MODULE
#include <linux/kernel.h>
#include <linux/module.h>
int init_module(void){
printk("<1>Hello,world!/n");
return 0;
}
void cleanup_module(void){
printk("<1>Goodbye cruel world!/n");
}
[root@localhost sin]# gcc -c test.c
[root@localhost sin]# insmod ./test.o
Warning: loading ./test.o will taint the kernel: no license
See http://www.tux.org/lkml/#export-tainted for information about tainted modules
Module test loaded, with warnings
提示没有授权??为什么有警告呢??
答:
从2.4.10版本内核开始,模块必须通过MODULE_LICENSE宏声明此模块的许可证,否则在加载此模块时,会收到内核被污
染"kernel tainted" 的警告。从linux/module.h文件中可以看到,被内核接受的有意义的许可证有 "GPL","GPL v2","GPL
and additional rights","Dual BSD/GPL","Dual MPL/GPL","Proprietary"。
在同时支持2.4与2.6内核的设备驱动中,模块可按如下方式声明自己的许可证。
下面:适用于2.4与2.6内核的模块许可证声明模板
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10)
MODULE_LICENSE("GPL");
#endif
修改后程序如下:
#define MODULE
#include <linux/kernel.h>
#include <linux/module.h>
# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10)
MODULE_LICENSE("GPL");
#endif
int init_module(void){
printk("<1>Hello,world!/n");
return 0;
}
void cleanup_module(void){
printk("<1>Goodbye cruel world!/n");
}
编译、 加载
[root@localhost sin]# gcc -c test.c
[root@localhost sin]# insmod ./test.o
[root@localhost sin]# rmmod ./test.o
晕还是没有教程说的那样,打印出 “hello world!”
用下面的方法查看下,结果如下:
[root@localhost sin]# cat /proc/modules
test 748 0 (unused)
看到了 test 被挂载了,想要的结果没有出来,有点郁闷。
翻看以前的笔记,有记录描述,用dmesg可以查看信息,操作如下:
[root@localhost sin]# dmesg
Hello,world!
Goodbye cruel world!
Hello,world!
Goodbye cruel world!
结果如上所示,因为前面多次操作insmod,rmmod,所以显示了两次 呵呵!
比较郁闷的是,为什么不能像教程那样呢?直接的打印出来提示信息呢?
非要用dmesg 这个命令呢?现在也没明白 。。。
PC端的操作暂告一段落!
上传到开发板上执行
上传到开发板后(方法前面都描述),做insmod时,提示如下错误。。。
# ls
erase test.o
# insmod ./test.o
./test.o: ELF file ./test.o not for this architecture
#
哦,知道什么原因了没?对,没有交叉编译,我是直接把PC上运行的test.o传到开发板啦,心太急噪了 呵呵!
重新编译代码,采用交叉编译方式编译
我看个教程用交叉编译arm-linux-gcc -I后跟的地址为:
-I/linuette/target/box/kernel/include
我对 -I后面的这个参数开始不太明白,但是觉得应该是指向内核的目录,而我的虚拟机上没有内核文件,于是就上网找了个内核,其版本与开发板的内核版本要一致。而我开发板的版本如下:
VIVI version 0.1.4 (kingmonkey@localhost.localdomain) (gcc version 2.95.2 200005
Linux version 2.4.18-rmk7-pxa1 (root@localhost.localdomain) (gcc version 2.95.3
20010315 (release)) #10 五 9月 16 11:06:47 CST 2005
CPU: ARM/CIRRUS Arm920Tsid(wb) revision 0
Machine: Samsung-SMDK2410
我下了个内核如:linux-2.4.18.tar 解压目录到:/s2410-linux/
编译时指定了 -I-I/s2410-linux/linux/include
居然报了下面的错误
[root@localhost sin]# arm-linux-gcc -I/s2410-linux/linux/include test.c
In file included from test.c:3:
/s2410-linux/linux/include/linux/module.h:297: linux/version.h: No such file or
directory
test.c:4: parse error
于是到/s2410-linux/linux/include 目录看了,有很多头文件也,就是没有version.h文件难道我下的 内核有问题了又??
上网搜索了下原因:
做make oldconfig,就会有相关的头文件了,但是我在做这个操作时,报错了。。。无奈放弃了,继续找内核 嘿嘿
找了个内核版本和开发板的内核版本一致的内核了
解压到 armsys2410目录下, -I 也指定了目录
但有报了下面的错误了。。。。
工夫不负有心人,终于找到了和板子上的内核一摸一样的内核了,小小兴奋一下!
内核文件释放到 /armsys2410目录去
先建立个目录,操作如下:
Mkdir armsys2410
由于内核文件放是在xp系统下放入,VM和XP的共享目录,所以做如下操作将放在XP共享目录下的内核文件COPY到 VM上刚建立的armsys2410内:
cp /mnt/hgfs/share/k* ./
在armsys2410下,释放内核文件
Tar –xjvf kernel_armsys_051221.tar.bz2
然后重新编译test.c文件,操作如下:
[root@localhost sin]# arm-linux-gcc -I/armsys2410/kernel/include test.c
/usr/local/arm/2.95.3/arm-linux/lib/crt1.o: In function `_start':
/usr/local/arm/2.95.3/arm-linux/lib/crt1.o(.text+0x2c): undefined reference to `main'
/tmp/ccVAmX8b.o: In function `init_module':
/tmp/ccVAmX8b.o(.text+0x10): undefined reference to `printk'
/tmp/ccVAmX8b.o: In function `cleanup_module':
/tmp/ccVAmX8b.o(.text+0x34): undefined reference to `printk'
collect2: ld returned 1 exit status
[root@localhost sin]#
咋了,还是有错呢???
噢,编译选项忘了加个 “-c” 下面的编译正常 嘿嘿
[root@localhost sin]# arm-linux-gcc -I/armsys2410/kernel/include -c test.c
[root@localhost sin]#
用ls命令查看,在当前目录生成了个test.o文件。
将 test.o文件 copy到 VM和XP共享目录
cp ./test.o /mnt/hgfs/share
上传test.o文件到开发板:
进入终端(TCP/IP方式)把test.o文件上传到开发板,如下:
# cd tmp
# ls
erase
选发送,选择test.o文件,传输结束后并查看,如下:
# # ls
erase test.o
修改权限
# chmod 777 test.o
# ls
erase test.o
# insmod test.o
在另个终端输出(COM1方式)
# Hello,world!
终端(TCP/IP方式)做如下操作
# rmmod test
终端输出(COM1方式)
#Goodbye cruel world!
至此,第一个模块的示例也成功了嘿嘿!