看来一段时间的 LDD3 感觉看是看得懂,理论性比较强,还是得自己动手实践啊.
今天自己动手实践了下,错误百出,遇到各种问题,在此作下记录,大家一起学习.
很简单的一个加载模块的驱动--Hello.
开始我在虚拟机下的Linux系统下实践.
下面是代码--hello.c:
#include
#include
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
直接gcc编译的话,会报错,找不到头文件.
在我们系统自带的内核代码树下 cd /usr/src/kernels/2.6.18-53.el5-i686/有这些代码的头文件,
/lib/modules/`uname -r`/build
这个目录下同样有这些文件.
我们可以采用下面的命令查找:
[root@localhost 2.6.18-53.el5-i686]# ls include/linux/ |grep init.h
init.h
[root@localhost 2.6.18-53.el5-i686]#
最好就是采用Makefie了.
下面是 Makefile 文件,这 Makefile 文件和 hello.c 必须在同一目录下.
obj-m:=hello.o
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 *.symvers
注意 `uname -r` 两边的标识符是 键盘上 1 左边的字符,不是单引号,或者我们可以用 $(shell uname -r) 来代替.
执行 make 命令:
[root@localhost drivers]# make
make -C /lib/modules/`uname -r`/build M=/home/yikai/drivers modules
make[1]: Entering directory `/usr/src/kernels/2.6.18-53.el5-i686'
CC [M] /home/yikai/drivers/hello.o
Building modules, stage 2.
MODPOST
CC /home/yikai/drivers/hello.mod.o
LD [M] /home/yikai/drivers/hello.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.18-53.el5-i686'
[root@localhost drivers]# ls
hello.c hello.ko hello.mod.c hello.mod.o hello.o Makefile Module.symvers
[root@localhost drivers]#
编译完成,产生了 hello.ko 文件.
可是执行 insmod hello.ko 命令,终端下没有打印信息.
[root@localhost drivers]# insmod hello.ko
[root@localhost drivers]#
其实我们可以在/var/log/messages 中看到打印的信息
cat /var/log/messages
Mar 26 14:07:15 localhost kernel: Hello, world
[root@localhost drivers]#
或者我们还可以使用 dmesg 来查看:
[root@localhost drivers]# dmesg |tail -3
Hello, world
Goodbye, cruel world
Hello, world
[root@localhost drivers]#
看不到打印信息是是由于
KERN_ALERT优先级不够高,这里需要修改为:KERN_EMERG,再次编译,加载模块即可以看到结果
需要注意的是只有超级用户才能加载和卸载模块.
另外,如果有多个文件,则按下列方式编写Makefile文件(file1.c、file2.c):
obj -m := modulename.o
module-objs := file1.o file2.o
hello.c程序不用改变.
按照上面的 Makefile 例子 编写 Makefie.
obj-m := hello.o
KERNELDIR = /opt/EmbedSky/linux-2.6.30.4
PWD := $(shell pwd)
INSTALLDIR = /home/yikai/modules
CROSS_COMPILE = arm-linux-
CC = $(CROSS_COMPILE)gcc
.PHONY:modules modules_install clean
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
modules_install:
cp hello.ko $(INSTALLDIR)
clean:
rm -rf *.o *.order .depend .*.cmd *.ko *.mod.c .tmp_versions *.symvers
最后 make ,得到我们需要的 hello.ko 文件:
[root@localhost arm]# ls
hello.c hello.ko hello.mod.c hello.mod.o hello.o Makefile modules.order Module.symvers
[root@localhost arm]#
再就是拷贝到开发板运行了.
下面说下我遇到的些问题:
1. 在 ARM9 的 Makefie 时候 得注释掉 CROSS_COMPILE 和 CC ,貌似在内核源代码下已经指定了,注释的话就不会报错,
但是偶然重启机器,发现上面的不注释也可以编译通过,我估计是我虚拟机下的 Linux 系统那时候抽风 找不到 指定的 交叉工具链.
2. 再就是 我在写头文件的时候,在头文件的 < > 尖括号内侧的两边 加了 空格,提示找不到头文件.
#include
#include
变成了:
#include < linux/init.h >
#include < linux/module.h >
报错:
/home/yikai/arm/hello.c:1:25: error: linux/init.h : No such file or directory
/home/yikai/arm/hello.c:2:27: error: linux/module.h : No such file or directory