《Linux设备驱动程序》学习笔记----开发前的准备工作

来源:互联网 发布:淘宝货源一般怎么找 编辑:程序博客网 时间:2024/06/05 03:57

 

      刚刚开始学linux设备驱动开发,看了点儿《linux设备驱动程序》这本书,但是,就在编译helloworld这个模块给卡住了,弄了好多天,才摸透,总结一下经验吧。

      1.系统的选择。我觉得这个其实也没什么,看个人习惯吧,我选择的是ubuntu,因为现在用的人多嘛,不过,当我编译内核的时候,我就后悔了,我用的是ubuntu默认的配置文件,结果编译过程足足花了我3个小时,当然,我是用我的笔记本编译的,那也算是老古董了,512的内存,嘿嘿!!

      2.内核编译的工具。编译过程涉及到的工具有make,automake,gcc,

build-essential,kernel-package, libncurses5-dev, fakeroot......一般在安装系统的时候,有这样的选项,只要把那个编译工具的选项选上就行了,fedora的好像是默认都安装了吧,但是在配置环境的时候要图形工具的支持,这个就得自己装了,上网搜搜就知道了,我空间里面也有。

       3.为自己的系统构建内核源代码树,这个就是关键了!2.6内核的模块要和内核源代码树中的目标文件链接,通过这种方式,可得到更加健壮的模块装载器,这样就需要这些目标文件存在于内核目录树中(摘自《linux设备驱动程序》) 。驱动程序和用户程序可不一样,它是作为一个模块连接到内核模块来运行的,运行在内核空间里面。所以要运行我们自己构造的模块,需要自己的系统已经配置好内核树,然后把目标模块和内核树连接起来运行!在我看来,其实就是要让我们的驱动程序能找到头文件声明的路径罢了,至于如何构建内核树,我搜了一下网上的文章,搜到最后,发现内核树是在编译内核的时候得到的,然后寻着前人的路,我又试了一遍,其中遇上一些问题,我都在我的空间里面说明了。

        4.makefile。当你经过漫长的等待后终于构建好了内核源代码树,兴致勃勃地跑到终端下敲了一下make结果发现还是有错误,你就该好好想想了,这已经不是源代码树的问题了,是你有没有读懂makefile!!刚刚开始的时候,我看了看makefile,没怎么看懂,就没有多加考虑,以为不是它的问题,是自己系统的问题,结果我错了,当我构建好了自己的源代码树的时候,make了一下,成功了,目录下终于出现了hello.ko,当时那个高兴呐!!鸡冻得内流满面啊!!结果insmod后,发现error inserting 'hello.ko': -1 Invalid module format......这回是脸干了......看着看着,感觉很熟悉,好像在ldd上看到过,果然,在31面正好说了!是版本依赖的问题,出现这样的问题,是因为我的模块和我正在运行的内核不兼容,意思就是你编译模块时使用的内核源代码树的版本号和系统现在运行的内核版本号不一致!为什么会这样呢??是因为没有看懂makefile啊!!

 

ifneq ($(KERNELRELEASE),)

 

 

obj-m := hello.o

else

PWD := $(shell pwd)

 

KERNELDIR := /lib/modules/ $(shell uname -r)/build

default:

    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

 

 

 

endif

        这是从ldd上摘抄下来的,书上说:该makefile将被读取两次,当makefile从命令行调用时,它注意到KERNELRELEASE变量尚未设置。我们可以注意到,已安装的模块目录中存在一个符号链接(就是那个build文件夹,括号里面的都是我说的!),它指向内核的构造树,这样这个makefile就可以定位内核的源代码目录。如果读者实际运行的内核并不是要构造的内核,则可以在命令行提供KERNELDIR=选项或者设置KERNELDIR环境变量,也可以修改用来设置KERNELDIR的行(其实就是修改makefile里面的KERNELDIR)。在找到内核源代码树之后,这个makefile会调用default:目标,这个目标是用先前描述过的方法第二次运行make命令(注意,在这个makefile中,make命令被参数化成了$(MAKE)),以便运行内核构造系统。(所以,第一次读取makefile,其实是为了找到内核源代码树和内核配置文件。)在第二次读取该makefile文件时,KERNELRELEASE变量已经被设置了,makefile文件已经设置了obj-m,这个时候,内核的makefile就负责真正构造模块了。

        说简单点儿,makefile第一次被读取时,执行的是else语句,第二次读取时执行的是if语句!这样够简单了!!(其实这和创建子进程执行的fork函数有几分相似,当然,区别是肯定有的!)哈哈!!

        第一次读取makefile文件时,执行else语句,通过-C $(KERNELDIR) 转入内核源代码树的路径并获取配置信息(之所以在这里说有配置信息,是因为我试过将KERNELDIR直接用源代码目录替代,结果make的时候提示

ERROR:Kernel configuration is invalid.inlude/generated/autoconf.h or include/config/auto.h are missing.Run 'make oldconfig && make prepare' on kernel src to fix it. 

WARNING:Symbol version dump /usr/src/linux-headers-2.6.35-22/Modules.symvers is missing;modules will have no dependencies and modvrsions.

这样的错误,如果有人知道为什么,请赐教!!谢谢!!),然后通过M=$(PWD)返回当前目录,第二次读取makefile,则执行if里面的语句,开始构造模块。

        好了,该解决的问题都解决了,开始的准备工作其实就这么多,想想刚刚开始的时候,屁颠屁颠地上网找和书上对应版本的发行版系统,天真地企图在2.6的内核上编译2.4的内核,真是自己都无语了,瞎忙活了那么多天,就沾到了编译内核的这么一点儿边,兜了一大圈,其实这些在ldd上都有提到过,主要是刚刚开始看的时候,并没有怎么留意,当然,也是因为自己对驱动方面的理解还不够,接触的不多,今天抽空看了第三章《字符设备驱动程序》,感觉有些概念还是有些生涩,读起来有点儿困难,但是,仅仅在第二章,就能学到那么多知识,最起码学了编译内核,配置内核,如何编写makefile,同时对驱动开发有了一个大体的认识,虽然这种认识还不成熟,而且个人感觉还很片面,忙活了几天,都还是在驱动开发的外面转悠,但是对以后的学习应该会有帮助,同时这也是一种激励嘛!最起码自己没有放弃!!这是很值得鼓励滴!!哈哈!!坚持就是胜利!!

        看来,对LDD这本书,还是应该要细嚼慢咽,多啃啃,还得加油啊!!

        文章哪里要是写的有问题,请大虾指正!一定虚心接受!!同时希望懂驱动开发的大牛们能多多指点迷津,小弟感激涕零!!

 

原创粉丝点击