Linux系统驱动全吗,揭秘linux驱动程序----都是关于模块

linux Device Drivers Demystified

James Andrews

Thursday, September 23, 1999 12:49:47 PM

Linux系统另一种广为人知的优势是-----它并不需要像其他操作系统那样,总是要重启(想一想,我们在windows下安装某些软件或驱动的时候,都是要重启系统才可以使软件完整地生效。)。你或许认为这是因为linux那岩石搬坚固的稳定性造就的。你也许认为,我准备谈论设备驱动程序的质量。如果你那样想的话,那么,你就错了。安装了linux设备驱动程序,然后并不需要重启系统的原因是,我们可以在不用重启动操作系统的基础下重新配置驱动,载入或者是卸掉它们。

要实现上面的那种功能,就必须用到模块化的内核驱动程序。

如何载入一个模块

很多人,在安装他们需要的模块的时候进行配置,完成之后,就不用再去理它们了。所有,主要的linux操作系统发行版,都采用了模块化的机制,因为,这让它们有另外的优势:系统大小(意思是说,在发行系统的时候,只发行核心的部分,其他,驱动程序方面的,你在需要的时候再自行载入。)。发行商,想让他们发行的linux操作系统,尽可能支持所有的扩展卡和设备。

如果发行商的确提供了几种支持一定数量的设备,内核定制好的linux操作系统(就是它支持的设备的驱动程序已经编译进内核了),那么这样的话操作系统的是很大的(很占磁盘空间的)。

采用模块化机制的系统,发行商可以提供一个只包含基本功能的操作系统,外加一系列linux设备驱动程序(这是不编译进内核的)。这种发行的操作系统大小只占两个或三个软盘。

如果你想在系统设置好之后,再添加一个模块到系统中,那么,最简单的办法是:

这个例子,用modprobe命令为苹果机上的系统,添加一个磁盘子系统驱动模块。如果(在添加)这一个模块时需要用到参数,比如系统中断请求号(每个系统都提供了一组中断请求,每个中断请求都有一个编号),那么你也可以通过modprobe命令来指定相应的中断请求号。

我们可以使用lsmod命令来查看系统中都安装了哪些模块,还有这些模块之间的关联性,依赖性。下面是使用lsmod命令后的输出结果:Module                  Size   Used by

gus                     45016    0

mad16                   6564     0

sb                       31416   0

ad1848                 15112     0  [mad16]

uart401                 5588     0  [mad16 sb]

sound                  54368    0  [gus mad16 sb ad1848 uart401]

在这个例子里面,mad16内核设备驱动程序依赖于ad1848驱动。

的确,存在一个mad16设备驱动程序,它是驱动一组声卡芯片的。

在通常情况下,我们在安装linux系统的时候,会编译一部分我们需要的驱动模块到系统中,这样的模块,在每次系统启动时都会载入(我们可以选择一些驱动模块不载入,在系统启动时)。

要达到这样的功能,我们就要用到/etc目录下的modules文件,这个文件里面列出了在系统启动时要载入的模块(我在自己的fedora系统中,在/etc目录下并没有找到这个modules文件,或许是因为系统版本不同吧。)。

所有模块的配置信息都存在/etc目录下的conf.modules文件中。建议不要手动去编辑这个conf.modules文件,不过呢,可以通过一个脚本来修改配置conf.modules,比如更新模块的脚本(这个作者点出的脚本update-modules应该是要自己编写的,并没有现成的可以给我们修改)。

要想了解更多的细节,可以查看man手册。

如何编译linux驱动模块

首先,我们要了解一下模块是如何别被构造的。模块的构造过程与用户空间的应用程序的构造过程有显著不同;内核是一个大的、独立的程序,对于它的各个部分如何组合在一起有详细的明确的要求。Linux2.6内核的构造过程也与以前版本的内核构造过程不同;新的构造系统用起来更加简单,并且可产生更加正确的结果,但是它看起来和先前的方法有很大不同。 内核的构造系统非常复杂,我们所看到的只是它的一小部分。如果读者想了解更深入的细节,则应阅读在内核源码中的Document/kbuild目录下的文件。在构造内核模块之前,有一些先决条件首先应该得到满足。首先,读者要保证你有适合于你的内核版本的编译器、模块工具,以及其他必要工具。在内核文档目录下的文件Documentation/Changes里列出了需要的工具版本;在开始构造内核前,读者有必要查看该文件,并确保已安装了正确的工具。如果用错误的工具版本来构造一个内核(及其模块),可能导致许多奇怪的问题。另外也要注意,使用太新版本的编译器偶尔可能也会导致问题。一旦做好了上面的准备工作之后,其实给自己的模块创建一个makefile则非常简单。实际上,对于本章前面展示的" hello world"例子,下面一行就够了:obj-m := hello.o如果读者熟悉make,但是对Linux2.6内核构造系统不熟悉的话,可能奇怪这个makefile如何工作。毕竟上面的这一行不是一个传统的makefile的样子。 问题的答案当然是内核构造系统处理了余下的工作。上面的赋值语句(它利用了由GNU make提供的扩展语法)说明有一个模块要从目标文件hello.o构造, 而从该目标文件构造的模块名称为hello.ko.如果我们想由两个源文件(比如file1.c和file2.c )构造出一个名称为module.ko的模块,则正确的makefile可如下编写:obj-m := module.omodule-objs := file1.o file2.o为了让上面这种类型的makefile文件正常工作,必须在大的内核构造系统环境中调用他们。假设读者的内核源码数位于~/kernel-2.6目录,用来建立你的模块的make命令(在包含模块源代码和makefile的目录下键入)应该是:make -C ~/kernel-2.6 M=`pwd` modules这个命令首先是改变目录到用-C选项指定的位置(即内核源代码目录),其中保存有内核的顶层makefile文件。这个M=选项使makefile在构造modules目标前,返回到模块源码目录。然后,modules目标指向obj-m变量中设定的模块,在上面的例子里,我们将该变量设置成了module.o。上面这样的make命令对于多个文件的编译显得不是很方便,于是内核开发者就开发了一种makefile方式,这种方式使得内核树之外的模块构造变得更加容易。代码清单1.4展示了makefile的编写方法:代码清单1.4 makefileifeq ($(KERNELRELEASE),)KERNELDIR ?= /source/linux-2.6.13PWD := $(shell pwd)modules:$(MAKE) -C $(KERNELDIR) M=$(PWD) modulesmodules_install:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_installclean:rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions.PHONY: modules modules_install cleanelseobj-m := hello.oendif我们再次看到了扩展的GNU make语法在起作用。在一个典型的构造过程中,这个makefile将被读取两次。当从命令行中调用这个makefile ,它注意到KERNELRELEASE变量尚未设置。我们可以注意到,已安装的模块目录中存在一个符号连接,它指向内核的构造树,这样这个makefile就可以定位内核的源代码目录。如果读者时间运行的内核并不是要构造的内核,则可以在命令行提供KERNELDIR=选项或者设置KERNELDIR环境变量,或者修改makefile中设置KERNELDIR的那一行。在找到内核源码树,这个makefile会调用default:目标,这个目标使用先前描述过的方法第二次运行make命令(注意,在这个makefile里make命令被参数化成$(MAKE)),以便运行内核构造系统。在第二次读取makefile时,它设置了obj-m,而内核的makefile负责真正构造模块。这种构造模块的机制看起来很繁琐,可是,一旦我们习惯了使用这种机制,则会欣赏内核构造系统带给我们的便利。需要注意的是,上面makefile并不完整,一个真正的makefile应包含通常用来清除无用文件的目标,安装模块的目标等等。一个完整的例子可以参考例子代码目录的makefile。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值