驱动程序添加到内核
一 . 概述: 在 linux 内核中增加程序需要完成以下三项工作: 1. 将编写的源代码复制到 Linux 内核源代码的相应目录 2. 在目录的 Kconfig 文件中增加新源代码对应项目的编译配置选项 3. 在目录的 Makefile 文件中增加对新源代码的编译条目 二 . 实例 1.
先把驱动代码
usbtmc(
文件夹
)
赋值到
/usr/src/linux-headers-2.6.32-31-generic/drivers/char
下
首先你要清楚你的模块应在内核源代码树中处于何处。 1> 设备驱动程序存放在内核源码树根目录 drivers/ 的子 目录下,在其内部,设备驱动文件进一步按照类别,类型等有序地组织起来。 a. 字符设备存在于 drivers/char/ 目录下 b. 块设备存放在 drivers/block/ 目录下 c.USB 设备则存放在 drivers/usb/ 目录下。 注意: (1) 此处的文件组织规则并非绝对不变,例如: USB 设备也属于字符设备,也可以存放在 drivers/usb/ 目录下。 (2) 例如我们把驱动程序 usbtmc 存放在 drivers/char/ 目录下,那么你要注意,在该目录下同时会存在大量的 C 源代码文件和许多其他目录。所有对于仅仅只有一两个源文件的设备驱动程序,可以直接 存放在该目录下,但如果驱动程序包含许多源文件和其他辅助文件,那么可以创建一个新子目录。 此处,我们是把 usbtmc 目录放在了 drivers/char 目录下面 2. 修改 char 目录下的 Kconfig 和 Makefile (1) 修改 Kconfig sudo gedit Kconfig 添加下面一句后 source "drivers/char/usbtmc/Kconfig" 它表示将 usbtmc 目录下的 Kconfig 挂载到 char 目录下的 Kconfig 里面 ( 为了使本层的 Kconfig 文件能起作用,我们需要修改父目录的 Kconfig 文件,加入 source 语句 ) 1> 对驱动程序而言, Kconfig 通常和源代码处于同一目录。 2> 如果你建立了一个新字目录,而且也希望 Kconfig 文件存在于该目录中的话,那么就必须在一个已存在的 Kconfig 文件中将它引入,需要用上面的 语句 将其挂接在 drivers/char 目录中的 Kconfig 中。 (2) 修改 Makefile 添加一句话: obj-$(CONFIG_USBTMC) +=usbtmc/ 这行编译指令告诉模块构建系统在编译模块时需要进入 usbtmc/ 子目录中。此时的驱动程序的编译取决于一个特殊配置 CONFIG_USBTMC 配置选项。 3. 现在在我们自己些驱动程序文件夹中添加 Kconfig 和 Makefile (1) 修改 Kconfig 新建一个 Kconfig 添加下面的话 menu "USBTMC" comment "USBTMC Driver" config USBTMC tristate "USBTMC" default n help If you say Y here,support for the usbtmc with computer interface will be compiled into he kernel and accessible via device node. You can also say M here and the driver will be built as a module named usbtmc.ko. If unsure,say N. endmenu endmenu 正确配置好后,我们在源码下执行 sudo make menuconfig 后,在出现的 Linux Kernel Configuration 图形界面中选择 Device Drivers 下的 character devcie 中 ,将会看到新加的 USBTCM 菜单, (2) 修改 Makefile 新建一个 Makefile ,添加下面的话 obj-$(CONFIG_USBTMC) +=usbtmc.o 此时,构建系统运行就将会进入 usbtmc/ 目录下,并且将 usbtmc.c 编译为 usbtmc.ko 模块 注: 如果驱动程序源文件可能不只有一个,可以把 Makefile 做如下修改: obj-$(CONFIG_USBTMC) +=usbtmc.o usbtmc-objs :=usbtmc-main.o usbtmc-usb1.o 此时, usbtmc-main.c 和 usbtmc-usb1.c 就一起被编译和连接到了 usbtmc.ko 某块中。 4. 现在已经 Ok 了,现在我们可以进入 linux 内核目录下通过 menuconfig 可以找到我们的 USBTMC 选项(在 Device_Drivers 下的 character devices 里可以找到 USBTMC )对其进行选定。然后退出,编译内核,就搞定了。
5. 删除: 删除也很简单,首先在 drivers/char 目录下删掉自己的驱动文件夹。其次再删除 Makefile 和 Kconfig 之前添加的东西,就搞定了 三 . 详解: Makefile
,
Kconfig
和配置工具组成了
Linux
2.6
内核的配置系统。
1. 在进入 menuconfig 配置界面时,会发现每个配置项目为布尔型(要么编译入内核,要么不编译,选项为“ Y” 或“ N” ),菜单上为配置选项的名字例如:“ XXX Driver”,help 后面的内容为帮助信息。 1> 除了布尔型的配置项目外,还存在一种三态型 (tristate) 配置选项,它意味着要么编译入内核,要么编译为内核模块,要么不编译,选项为“ Y” ,“ M” 或“ N” 。 eg: obj-$(CONFIG_USBTMC) +=usbtmc.o 上面的脚本含义是:如果 USBTMC 选项被选择为“ Y” 或“ M” ,即 obj-$(CONFIG_USBTMC) 就等同于 obj-y 或 obj-m 时,则编译 usbtmc.c ,选 Y 的情况直接会将生成的目标代码直接连接到内核,为“ M” 的情况则会生成模块 usbtmc.ko ,如果 USBTMC 配置选项被选择为“ N” ,即 obj-$(CONFIG_USBTMC) 等同于 obj-n 时,则不编译 usbtmc.c 2.Makefile 对内核源代码各级子目录中的 kbuild Makefile 进行介绍, (1) 目标定义 目标定义用来定义哪些内容要作为模块编译,哪些要编译并连接进内核 (a)obj-y:=foo.o 表示要由 foo.c 或者 foo.s 文件编译得到 foo.o 并连接进内核,而 obj-m 则表示该文件要作为模块编译。处了 y,m 以外的 obj-x 形式的目标都不会被编译。 ( b) 我们最常用的的做法是根据 .config 文件的 CONFIG_ 变量来决定文件的编译方式: eg: obj-$(CONFIG_ISDN) +=isdn.o (c) 多个文件模块的定义 如果一个模块由多个文件组成,这时候应采用模块名加 -objs 后缀或者 -y 后缀的形式来定义模块的组成文件。 如: obj-$(CONFIG_EXT2_FS) +=ext2.o ext2-y :=balloc.o bitmap.o 模块的名字是 ext2, 由 balloc.o 和 bitmap.o 两个文件最终连接生成 ext2.o 直至 ext2.ko 文件。 3.Kconfig 内核配置脚本语法: (1) 大多数的内核配置选项都对应一个 Kconfig 中的一个菜单入口。 menu "USBTMC" comment "USBTMC Driver" config USBTMC tristate "USBTMC" default n endmenu (a)“config” 关键字定义新的配置选项,之后的几行定义了该配置选项的属性。配置选项的属性包括类 型,数据 , 输入提示,依赖关系(及反向依赖关系),帮助信息和默认值等。 (b) 每个配置选项都必须指定类型,其他类型都基于这两种基本类型。类型定义后可以紧跟输 入提示,下面两个脚本是等价的 脚本 1 : bool “Networking support” 脚本 2 : bool promt “Networking support” 输入提示的一般格式如下提示: prompt <prompt> [if <expr>] 其中可选的 if 用来表示该提示的依赖关系。 默认值的格式如下所示: default <expr> [if <expr>] 一个配置选项可以存在任意多个默认值,这种情况下,只有第一个被定义的值是可用的。如果用户不设置对应的选项,配置选项的值就是默认 值。 (c) 依赖关系的格式如下所示: depends on ( 或者 requires) <expr> 如果定义了多个依赖关系,它们之间用” &&” 间隔。依赖关系也可以应用到该菜单中所有的其他选项中。 (4) 反向依赖关系的格式如下所示: select <symbol> [if <expr>] A.depends 能限定一个 symbol 的上限,即如果 A 依赖于 B ,则在 B 被配置为“ Y” 的情况下, A 可以为“ Y” ,“ M” 和” N”; 在 B 被配置为“ M” 的情况下, A 可以被配置为“ M” 或“ N” ; B 在被配置为“ N” 的情况下, A 只能为” N” 。 B.select 能限定一个 symbol 的下限,若 A 反向依赖于 B ,则 A 的配置值会高于或等于 B (正好与 depends 相反)。如果 symbol 反向依赖于多个对象,则它的下限是这些对象的对大值。 (5) 帮助信息的格式如下: help( 或 ---help---) 开始 。。。 结束 帮组信息完全靠文本缩进识别结束。“ ---help---” 和” help” 的初衷在于将文件中的配置逻辑与给开发人员的提示分开。
3. 菜单结构 菜单入口在菜单数结构中的位置可由两种方法决定。 (1) 第一中方式如下所下: menu “Network device support” depends on NET config NETDEVICES
endmenu 所有处于” menu” 和” endmenu” 之间的菜单入口都会成为“ Network device support” 的子菜单。而且,所有子菜单选项都会继承父菜单的依赖关系,比如:“ Network device support” 对“ NET” 的依赖被加到了配置选项 NETDEVICES 的依赖列表中。 (2) 另一种方式是通过分析依赖关系生成菜单结构。如果菜单选项在一定程度上依赖于前面的 选项,它就能成为该选项的子菜单。如果父选项为“ N” ,则子选项不可见;如果父选项为“ Y” 或“ M” ,则子选项可见。 Eg: config MODULES bool “Enable loadable module support” config MODVERSIONS bool “Set version information on all module symbole” depends on MODULES
comment “module support disabled”
depends on !MODULES
MODVERSIONS 直接依赖 MODULES ,如果 MODULES 不为“ N” ,该选项才可见。 (3) 除此之外, Kconfig 中还可能使用“ choices …...endchoice”,”comment”,”if....endif” 这样的语法结构。 其中 choice <choice options> <choice block> enchoice 它定义一个选择群,其接受的选项( choice options )可以是前面描述的任何属性。在一个硬件有多个驱动的情况下使用,使用选择可以实现 最终只有一个驱动被编译进内核或模块。选择群还可以接受的另一个选项是“ optional”, 这样菜单入口就被设置为“ N” ,没有被选中。 |
|