本文详细阐述了Linux驱动KO的编译方法,重点介绍单编驱动KO的流程与优势。在Linux系统中,.ko文件即模块文件,Linux提供了模块机制,具有不直接影响内核映像大小与加载后功能等同于内核内其他部分的特点。
实验环境包括MINI2440开发板与基于linux-2.6.32.2的软件环境。编译Linux驱动KO主要分为两种方式:整编内核与单编KO。
整编内核模式下,通过将驱动程序demo_driver.c拷贝至指定目录,调整Makefile文件,然后在内核源码顶层目录执行编译指令,最终生成demo_driver.ko文件。然而,这种方式涉及整个内核的编译过程,耗时约20分钟。
单编KO方法则更简洁。使用make moles指令编译内核中所有模块,或通过增加“M”参数指定单独编译某一模块。单编KO模式下,需要一个特殊的Makefile文件,该文件定义了内核目录、交叉编译工具等变量,指定将demo_driver.c编译成demo_driver.ko文件。通过简单的make指令,编译过程只需3秒左右,效率显着提高。
编译完成后,将demo_driver.ko文件传输至开发板中并加载,通过查看设备与测试驱动,确保其正常运行。单编KO模式优势在于快速编译过程,这使得开发者在调试和迭代驱动程序时更为高效。
总结,Linux驱动KO的编译方法主要包括整编内核与单编KO两种。单编KO方法以其快速编译优势成为一种高效且实用的选择。如果您觉得本文对您有所帮助,请给予支持与反馈,您的认可是我持续更新的动力。
B. linux内核设备驱动——将驱动程序编译进内核
将驱动程序编译进Linux内核,实际上是将模块集成到内核的编译过程中。开发阶段通常会先创建.ko文件,然后通过modprobe或insmod加载。modprobe更智能,能处理依赖,而insmod则可能需要开发者自行解决依赖问题。
编译驱动程序进内核涉及的步骤更为复杂,需要对Linux源码的编译规则有深入理解。一般有本机编译和交叉编译两种方式。本机编译方便,但生成的镜像无法改动,而交叉编译则需要在PC上构建编译环境,针对目标平台进行,以获取更好的性能。
关键步骤包括配置内核(make menuconfig),配置完成后编译源码,通过Kconfig文件管理和编译选项指定驱动源文件。驱动源文件会被添加到内核编译树中,只有当相关配置被选中(如CONFIG_CDEV_TEST)时,驱动才会被编译。最后,生成的模块需要复制到目标主机的/lib/moles目录下,并在启动时进行验证。
总的来说,将驱动编译进内核涉及源码管理、配置、编译和部署,是一个系统性的过程,需要对Linux内核有深入理解才能完成。
C. 如何把自己的驱动编译进内核或模块
我们知道若要给Linux内核添加模块(驱动)有如下两种方式:
(1)动态方式:采用insmod命令来给运行中的linux加载模块。
(2)静态方式:修改linux的配置菜单,添加模块相关文件到源码对应目录,然后把模块直接编译进内核。
对于动态方式,比较简单,下面我们介绍如何采用静态的方式把模块添加到内核。
最终到达的效果是:在内核的配置菜单中可以配置我们添加的模块,并可以对我们添加的模块进行编译。
一. 内核的配置系统组成
首先我们要了解Linux 2.6内核的配置系统的原理,比如我们在源码下运行“make menuconfig ”为神马会出现一个图形配置菜单,配置了这个菜单后又是如何改变了内核的编译策略滴。
内核的配置系统一般由以下几部分组成:
(1)Makefile:分布在Linux内核源代码中的Makefile,定义Linux内核的编译规则。
(2)配置文件(Kconfig):给用户提供配置选项,修改该文件来改变配置菜单选项。
(3)配置工具:包括配置命令解释器(对配置脚本中使用的配置命令进行解释),配置用户界面(提供字符界面和图形界面)。这些配置工具都是使用脚本语言编写的,如Tcl/TK、Perl等。
其原理可以简述如下:这里有两条主线,一条为配置线索,一条为编译线索。配置工具根据kconfig配置脚本产生配置菜单,然后根据配置菜单的配置情况生成顶层目录下的.config,在.config里定义了配置选择的配置宏定义,如下所示:
如上所示,这里定义的这些配置宏变量会在Makefile里出现,如下所示:
然后make 工具根据Makefile里这些宏的赋值情况来指导编译。所以理论上,我们可以直接修改.config和Makefile来添加模块,但这样很麻烦,也容易出错,下面我们将会看到,实际上我们有两种方法来很容易的实现。
二. 如何添加模块到内核
实际上,我们需要做的工作可简述如下:
(1)将编写的模块或驱动源代码(比如是XXOO)复制到Linux内核源代码的相应目录。
(2)在该目录下的Kconfig文件中依葫芦画瓢的添加XXOO配置选项。
(3)在该目录的Makefile文件中依葫芦画瓢的添加XXOO编译选项。
可以看到,我们奉行的原则是“依葫芦画瓢”,主要是添加。
一般的按照上面方式又可出现两种情况,一种为给XXOO驱动添加我们自己的目录,一种是不添加目录。两种情况的处理方式有点儿不一样哦。
三. 不加自己目录的情况
(1)把我们的驱动源文件(xxoo.c)放到对应目录下,具体放到哪里需要根据驱动的类型和特点。这里假设我们放到./driver/char下。
(2)然后我们修改./driver/char下的Kconfig文件,依葫芦添加即可,如下所示:
注意这里的LT_XXOO这个名字可以随便写,但需要保持这个格式,他并不需要跟驱动源文件保持一致,但最好保持一致,等下我们在修改Makefile时会用到这个名字,他将会变成CONFIG_LT_XXOO,那个名字必须与这个名字对应。如上所示,tristate定义了这个配置选项的可选项有几个,help定义了这个配置选项的帮助信息,具体更多的规则这里不讲了。
(3)然后我们修改./driver/char下的Makefile文件,如下所示:
这里我们可以看到,前面Kconfig里出现的LT_XXOO,在这里我们就需要使用到CONFIG_XXOO,实际上逻辑是酱汁滴:在Kconfig里定义了LT_XXOO,然后配置完成后,在顶层的.config里会产生CONFIG_XXOO,然后这里我们使用这个变量。
到这里第一种情况下的添加方式就完成了。
四. 添加自己目录的情况
(1)在源码的对应目录下建立自己的目录(xxoo),这里假设为/drivers/char/xxoo 。
(2) 把驱动源码放到新建的xxoo目录下,并在此目录下新建Kconfig和Makefile文件。然后给新建的Kconfig和Makefile添加内容。
Kconfig下添加的内容如下:
这个格式跟之前在Kconfig里添加选项类似。
Makefile里写入的内容就更少了:
添加这一句就可以了。
(3)第三也不复杂,还是依葫芦画瓢就可以了。
我们在/drivers/char目录下添加了xxoo目录,我们总得在这个配置系统里进行登记吧,哈哈,不然配置系统怎么找到们呢。由于整个配置系统是递归调用滴,所以我们需要在xxoo的父目录也即char目录的Kconfig和Makefile文件里进行登记。具体如下:
a). 在drivers/char/Kconfig中加入:source “drivers/char/xxoo/Kconfig”
b). 在drivers/char/Makefile中加入:obj-$(CONFIG_LT_XXOO) += xxoo/
添加过程依葫芦画瓢就可以了,灰常滴简单。
D. 如何编译驱动程序
驱动的编译和上层应用程序的编译完全不同,作为初学者应该先了解一下,即使你还不懂得怎么写驱动程序。
首先安装DDK,然后随便找一个例子来测试。在菜单中找到BUILD环境菜单执行,不同的系统要使用不同的BUILD环境。会打开一个DOS窗口,这时CD到那个例子程序,输入 build –cZ回车就可以了。 驱动程序都是用一个由DDK提供的叫build.exe的工具编译的。此程序以一个名为SOURCES的文件作为输入,该文件中包含目标可执行文件的名称、类型和要创建的可执行文件的路径,注意这个文件没有后缀名。
SOURCES的文件格式:
TARGETNAME=drivername ,
- 本参数用于指定生成的设备驱动程序名称(不需后缀名),所产生的文件
- 为drivername.sys.
TARGETPATH=./lib
- 本参数用于指定生成的设备驱动程序所存放的路径. 一般采用./lib.
TARGETTYPE=DRIVER
- build能够生成许多不同的目标对象,设备驱动程序一般选用 DRIVER.
INCLUDES=path1;path2;...
- 本参数是可选的, 用于指定其他的#include文件的搜索路径.
TARGETLIBS=lib1;lib2;...
- 本参数是可选的, 用于指定其他的lib库文件的搜索路径.
SOURCES=file1.c file2.c ...
- 本参数用于指定需被编译的全部源文件名称, 后缀名不能省略,文件名之间用空格分开.
SOURCES文件是必需的,如果没有它则表示没有任何源文件需要编译。
如果要换行可以用 ‘/’ 符号,表示对上一行的继续。
也可以创建DIRS文件,DIRS文件用于指定在当前目录下必须创建的子目录。
DIRS文件格式:
DIRS文件的内容由一系列用空格分开的目录名组成
DIRS = /
subdir1 /
subdir2 /
subdir3
DIRS文件是可选的。
有的时候,会提示找不到依赖的文件(.h,.lib 之类),其实设置好 source 文件的
INCLUDES和TARGETLIBS就可以,我第一次编译时就碰到这个问题,和VC环境区别较大,但习惯就好。
E. 怎么将驱动源代码编译进linux系统
一、 驱动程序编译进内核的步骤
在 linux 内核中增加程序需要完成以下三项工作:
1. 将编写的源代码复制到 Linux 内核源代码的相应目录;
2. 在目录的 Kconfig 文件中增加新源代码对应项目的编译配置选项;
3. 在目录的 Makefile 文件中增加对新源代码的编译条目。
bq27501驱动编译到内核中具体步骤如下:
1. 先将驱动代码bq27501文件夹复制到 ti-davinci/drivers/ 目录下。
确定bq27501驱动模块应在内核源代码树中处于何处。
设备驱动程序存放在内核源码树根目录 drivers/ 的子目录下,在其内部,设备驱动文件进一步按照类别,类型等有序地组织起来。
a. 字符设备存在于 drivers/char/ 目录下
b. 块设备存放在 drivers/block/ 目录下
c. USB 设备则存放在 drivers/usb/ 目录下。
注意:
(1) 此处的文件组织规则并非绝对不变,例如: USB 设备也属于字符设备,也可以存放在 drivers/usb/ 目录下。
(2) 在 drivers/char/ 目录下,在该目录下同时存在大量的 C 源代码文件和许多其他目录。所有对于仅仅只有一两个源文件的设备驱动程序,可以直接存放在该目录下,但如果驱动程序包含许多源文件和其他辅助文件,那么可以创建一个新子目录。
(3) bq27501的驱动是属于字符设备驱动类别,虽然驱动相关的文件只有两个,但是为了方面查看,将相关文件放在了bq27501的文件夹中。在drivers/char/目录下增加新的设备过程比较简单,但是在drivers/下直接添加新的设备稍微复杂点。所以下面首先给出在drivers/下添加bq27501驱动的过程,然后再简单说明在drivers/char/目录下添加的过程。
2. 在/bq27501下面新建一个Makefile文件。向里面添加代码:
obj-$(CONFIG_BQ27501)+=bq27501.o
此时,构建系统运行就将会进入 bq27501/ 目录下,并且将bq27501.c 编译为 bq27501.o
3. 在/bq27501下面新建Kconfig文件。添加代码:
menu "bq27501 driver"
config BQ27501
tristate"BQ27501"
default y
---help---
Say 'Y' here, it will be compiled into thekernel; If you choose 'M', it will be compiled into a mole named asbq27501.ko.
endmenu
注意:help中的文字不能加回车符,否则make menuconfig编译的时候会报错。
4. 修改/drivers目录下的Kconfig文件,在endmenu之前添加一条语句‘source drivers/bq27501/Kconfig’ 对于驱动程序,Kconfig 通常和源代码处于同一目录。 若建立了一个新的目录,而且也希望 Kconfig 文件存在于该目录中的话,那么就必须在一个已存在的 Kconfig 文件中将它引入,需要用上面的语句将其挂接在 drivers 目录中的Kconfig 中。
5. 修改/drivers目下Makefile文件,添加‘obj-$(CONFIG_BQ27501) +=bq27501/’。这行编译指令告诉模块构建系统在编译模块时需要进入 bq27501/ 子目录中。此时的驱动程序的编译取决于一个特殊配置 CONFIG_BQ27501 配置选项。
6. 修改arch/arm目录下的Kconfig文件,在menu "Device Drivers……endmenu"直接添加语句
source "drivers/bq27501/Kconfig"