在搭建驱动开发环境时出了不少的问题,现在汇总一下,只为帮助后来者。
帖子大多数技术并非原创,而是收集了,网上的大部分相关资料的一些汇总。但一下所有内容都为本人亲自实践后,才敢发出来的。
吐槽:在两天半的时间里我都不知道将虚拟机装了多少遍了,Ubuntu的9.10 10.10 11.04 11.10 每个我都试过。唉!
好了下面正式介绍一下整个搭建驱动开发环境的过程:
先来介绍一下我的最后开发环境。
虚拟机 ubuntu10.10。内核为2.635-22 。
上面的环境很重要,因为在不同的环境,相同的操作可能出现不同和报错,
当然解决办法也都不一样。
现在从我出现的第一个错误开始讲起:
1、在用gcc 编译Hello_world.c 驱动时提醒缺少linux/module.h 头文件。
刚开始我真的不知道开发驱动还要先搭建一下环境,就想网友说的。
我还以为有了linux和gcc这几个,就能开发驱动了呢,开始不是。查了一下需要先构造内核树。
2、构建内核树是出现的问题,和一些解决方法。
这类帖子,网上虽然说是比较多的,但是我发现好像都已来自同一篇文章。而且还是比较早的文章。你可以参考一下。http://www.cnblogs.com/hoys/archive/2010/10/29/1864536.html 等等。
主要的步骤就是:
a)当然你要提前安装好gcc,make,gdb等常用的编译和调试软件。可以参考http://www.codesky.net/article/200810/74361.html 等等。
b)构建内核树,可以参考http://www.cnblogs.com/hoys/archive/2010/10/29/1864536.html
构造内核树的一般步骤总结:
1)先查看自己OS使用的内核版本
root@ubuntu:~#uname -r
我查看后的结果是:2.6.35-22-generic
ubuntu一般系统在安装时 都会自行的安装linux-headers 例如在
如果安装系统时,自动安装了源码。在/usr/src目录下有对应的使用的版本目
录。例如下(我是自己下的)
root@ubuntu:/usr/src#ls
linux-headers-2.6.35-22
linux-headers-2.6.35-22-generic
一般ubuntu中都没有现成的源码
查看一下可一下载的源码包(我用的是ubuntu10.10,,直接在超级用户下使用此
命令没有任何问题,如果你使用的时候提示没有此命令的话,请改用普通用户)
root@ubuntu:/usr/src#apt-cache search linux-source
linux-source-Linux kernel source with Ubunt up atches
linux-source-2.6.35-Linux kernel source forversion2 .6.35 with Ubuntu
patches
root@ubuntu:/usr/src#
选择linux-source-2.6.35-Linux kernel source forversion 2.6.35 with Ubuntu
patches
然后使用install命令,详细命令如下:
root@ubuntu:/usr/src#apt-get install linux-source-2.6.35
下载完成后,在/usr/src下会出现一个目录linux-source-2.6.35和一个压缩包链
接linux-source-2.6.35.tar.bz2,直接切换到linux-source-2.6.35目录下,在这个
目录下有三个目录(debian、debian.master、linux-source-2.6.35)和一个压缩
包(linux-source-2.6.35.tar.bz2),
然后切换到/usr.src/linux-source-2.6.35/linux-source-2.6.35/目录下
注意以下操作最好在超级用户模式
所有的源代码都在该目录下。
开始配置内核选择最快的原版的配置(默认)方式(我是如此)
root@ubuntu:/usr/src/linux-source-2.6.35#make oldconfig
当然你也可以使用自己喜欢的配置方式如:menuconfig,xconfig(需GTK环境)。
反正不用剪裁什么,所以不管那种方式能配置它就行了。
root@ubuntu:/usr/src/linux-source-2.6.35#make
root@ubuntu:/usr/src/linux-source-2.6.35#make bzImage
因为我在这里用的是虚拟机所以编译的时间比较长。让我熬了两个通宵。唉!
如果你也用的是虚拟机的话,再如果你也是在晚上完成这个的话,我个人建议你定一个闹钟,两个小时后再来看结果。等的滋味不好受啊。
了,其实大部分时间都是用来执行make的。执行结束后,可以看到在当前目录
下生成了一个新的文件:vmlinux,其属性为-rwxr-xr-x。
然后:
root@ubuntu:/usr/src/linux-source-2.6.35#make modules/*编译模块*/
这一块的时间也不短,估计也要一个小时*(虚拟机)
root@ubuntu:/usr/src/linux-source-2.6.35#make modules_install/*安装模块*/
执行结束之后,在/lib/modules下会有两个目录(2.6.35.14和
2.6.35-22-generic),其中2.6.35.14就是新生成的目录。
对!这里就是2.6.35.14 。我确定,就是!这一点到后面出现问题的时候很对你很重要。
在随后的编译模块文件时,要用到这个路径下的build目录。至此,内核编
译完成。可以重启一下系统。
内核树就建立好了。
下面就将《LINUX设备驱动程序第三版》的P22中的helloworld运行一遍,来
验证一下吧。
我的文件放在/root/ldd3/hello/目录下创建2个文本文件hello.cMakefile
//hello.c
#include<linux/init.h>
#include<linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello,world\n");
return0;
}
static void hello_exit(void)
{
printk(KERN_ALERT"Goodbye,cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
#Makefile
Ifneq($(KERNELRELEASE),)
obj-m:=hello.o
else
KERNELDIR?=/lib/modules/$(shell uname -r)/build
PWD:=$(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
注意Makefile中的Tab键 然后make
root@ubuntu:~/ldd3/hello#make
root@ubuntu:~/ldd3/hello#insmod hello,ko
root@ubuntu:~/ldd3/hello#rmmmod hello
加载和移除模块
按照书上的例子 会在终端显示 hello , world 但是运行后什么都没有出现,原因
如下:
在虚拟机中的 linux 下编写“hello world“这个模块的时候,调内核中的输出函数
printk()时,在终端并不显示任何东西,这是由于使用的是虚拟机的问题。在
Ubuntu10.10(内核版本是 2.6.35.14)中它的输出语句输出到了系统日志文件
/var/log/syslog 中 。 在 RedHat 中 的 默 认 是 没 有 这 个 文 件 的 ( 但 可 以 配 置
/etc/syslog.conf 让系统生成该日志文件),所以,如果在你的虚拟机中安装的
linux 是 RedHat 版本的话,输出语句就会输出到/var/log/messages 中。
查看模块加载和删除时的情况:
完成。
这里我还需要强掉一下,如果你是在看到别的帖子后并且有很多的相关操作后才看到这个帖子的。你极有可能已经在相关的环境下更改了我们这里所需要的文件。也就是说既有可能报错。现在我总结一下我在编译的时候出现的一些错误:
1、Hello.ko 编译没有通过。
a)查看你在构造内核完成后,执行结束之后,在/lib/modules下会有两个目录(2.6.35.14和
2.6.35-22-generic),其中2.6.35.14就是新生成的目录。就有人不重视。(比如我)搞到最后连提醒的错误都不认识
b) 编译通过,但在加载驱动的时候出现:
嗯!就是这个Invalid module format。这就是我为什么要强调,最后我们在在
/lib/modules下会有两个目录
(2.6.35.14和2.6.35-22-generic)看准就是2.6.35.14而不是2.6.35.22。
为什么,我要这么说呢,
因为但多数情况,在加载内核时出现Invalid module format 时。
可能是因为你自己后来构造的内核树的版本和自己内核的版本不一致造成的。当别人这么说时,
你是否也怀疑自己是错在这里了呢。
(至少我一开始是这样的)网上关于Invalid module format
的解决办法也有很多而都数都是说解决版本不一致的办法。
(错误的让我操作了n回,还是错。让我装了n回 虚拟机,还是错)
最后发现在这里极有可能是你的Makefile 是书写错了,有人就说既然Makefile错了为什么还能生成Hello.ko呢?
因为这里你错在了依赖的lib库上,而不是语法上。
你可以对比一下网上不同版本hello_world的Makefile 。
是不是大不一样。所以当你确定自己的内核树没有构建错误时,
那就认真的检查你的Makefile。对于刚进入驱动开发的人来说,没有比较好的办法,
只有多试、多改、多查。提示:这里讲的是Ubuntu的驱动搭建过程,
如果你是要在其他环境搭建驱动开发环境的话,阅读此博客,你要学会多变通。