基本所有程序的例子都是经典的HELLO WORLD程序。
对于Linux设备驱动也不例外
http://blog.csdn.net/lintax/article/details/4590922
这个博主写的已经相当详细,
/*================hello-driver.c==============*/
#include <linux/module.h> /*所有模块都需要的头文件*/
#include <linux/kernel.h>
#include <linux/init.h> /* init和exit相关宏*/
MODULE_LICENSE("Dual BSD/GPL"); #《1》
MODULE_AUTHOR("CCC");
static int hello_init(void)
{
printk(KERN_ALERT " Hello Davinci!/n");
return 0;
}
static void hello_exit(void)
{
printk( KERN_ALERT " Goodbye, Davinci./n ");
}
module_init(hello_init);
module_exit(hello_exit);
/*================hello_davinci.c end===========*/
给其配个Makefile文件:
/*================Makefile==================*/
obj-m := hello_davinci.o
KERNELDIR := /opt/ti-davinci/
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
/*================Makefile end===============*/
好了,编译吧。
我的好心情立马被扑灭了,error,又见error:
我刚开始遇到一个问题就是编译不了
: *** 没有规则可以创建“/home/dvevm_1_20/myexample/hello-driver/hello-davinci.o”需要的目标“/home/dvevm_1_20/myexample/hello-driver/hello-davinci.c”。 停止。
原因是我把文件名命名成hello-driver.c 但是Makefile里面写的是 obj-m := hello_davinci.o
因为Make命令只会查找跟目标文件名相同的.c源文件,如果obj-m后面是hello_davinci.o 当然源文件名就应该是hello_davinci.o
当然如果把Makefile里面的hello_davinci.o 改成hello-driver.o 是一样的道理
楼主说的 找不到/opt/ti-davinci/include/asm/ 下的某个头文件这个错误我没有遇到,因为在编译前我就先把内核编译过一次,
故如果做内核驱动,必须先编译内核一次,以避免此类错误,个人理解。
转移到davinci开发板上,执行插入模块命令:
insmod hello-driver.ko
输出信息:
insmod: error inserting 'hello.ko': -1 Invalid module format
百度谷歌了一圈,发现基本原因就是编译时选择的内核跟实际运行的内核版本不匹配,我用的是TI官方的源码
/opt/mv_pro_5.0/montavista/pro/devkit/lsp/ti-davinci
但是这个代码应该跟开发板提供的源码有所区别,虽然我用uname -r查看是一样的,具体有什么区别就不得而知了。
把Makefile里面源码路径改成开发板提供的源码路径就可以用insmod hello_world.ko命令挂载
通过lsmod查看,也有了hello_world 模块。
然后执行移除模块命令:
rmmod hello-driver.ko
输出信息:
Goodbye Davinci.
再用lsmod来查看,就找不到hello_davinci了。
有时候会出现insmod: error inserting 'hello-driver.ko': -1 File exists
就是你原来加载过,但是没有卸载,又尝试去重新加载,肯定会提示已经存在。
有以下几点要注意:
1,所使用的内核环境必须是编译过的,否刚会出现链接之类的问题
2,对于编译过程中类似于:不能创建hello_davinci.o.tmp文件的错误。说明权限不够,可更改hello_davinci.c Makefile文件所在目录的属性,或者是sudo到根用户。我用的直接是root用户,所以不存在权限问题
3,hello_davinci.c文件中调用的头文件的作用:
init.h中的module_init(),module_exit()
kernel.h中的printk(),KERN_ALERT
module.h中的MODULE_LICENSE()
如果不使用MODULE_LICENSE()这个宏,会出现内核污染如
Warning: loading #.o will taint the kernel: no license
之类的错误,这只是个警告,应该要要告知版权之类的意思。
4,Makefile文件分析
obj-m := hello_world.o 代表了我们要构造的模块名为hello_world.o,make 会在该目录下自动找到hello_world.c文件进行编译。如果 hello_world.o是由其他的源文件生成(比如file1.c和file2.c)的,则在下面加上:
hello_world-objs := file1.o file2.o ......
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
其中 -C $(KERNELDIR) 指定了内核源代码的位置,其中保存有内核的顶层
makefile文件。
M=$(PWD) 指定了模块源代码的位置。
modules目标指向obj-m变量中设定的模块。
5,驱动模块运行在内核空间,运行时不能依赖于任何函数库和模块连接,所以在写驱动时所调用的函数只能是作为内核一部分的函数。
编译内核时,MAKEFILE会自动把生成的uImage 转移到 /arch/arm/boot目录我开发板用的民NFS,所以想在Makefile中自己加上代码,直接把生成的HELLO_WORLD.KO自动复制到开发板的文件系统中,用SHELL判断,如果没有直接复制过去,如果原来有的话先删除再复制,然后就是一系列悲催的错误
make[1]: Leaving directory `/home/dvevm_1_20/myexample/EL6446_kernel'
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [install] 错误 2
一直是语法错误,因为我写MAKEFILE内容基本都是差不多,估计是因为MAKE命令对格式太敏感,有少许不对就会出现格式错误,SHELL命令执行不了,因为内容很简单,参考书上语法分析也不是内容错误,只有不断调整格式,注意个人书写习惯,别的我也没找到很好的办法
上图是没有错误的,可以正确运行。
后面加上 \ 是相当于只启动一个SHELL执行所有命令,注意then else 这些关键词后面没有 ;
上面就是判断如果有hello-driver.ko 就提示 已经存在,如果没有,就从当关目录复制过去
几个用到的命令 modinfo
root@172.18.219.128:/home/dvevm# modinfo hello-driver.ko
filename: hello-driver.ko
author: davinci
license: Dual BSD/GPL
depends:
vermagic: 2.6.10_mvl401-davinci_evm preempt ARMv5 gcc-3.4
这个命令会出现模块相应信息,author在模块中MODULE_AUTHOR()宏定义davinci这个信息
很多 insmod: error inserting 'hello.ko': -1 Invalid module format
据说就是vermagic对不上,也就是内核版本不对,根据这个可以看一下