驱动程序添加到内核
一
.
概述:
在
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
内核的配置系统。
其中
Makefile
定义了
Linux
内核的编译规则,它是大型项目开发的产物。
Linux
环境下的大型项目开发中,系统被分为很多模块,而这些模块一般会经历几次修改,而在修改后的编译过程中,由于某些文件中存在依赖关系,人工编译效率低
(
有些文件不需要重新编译
)
且易出错,
Makefile
文件便应运而生。
Makefile
文件定义了模块间的依赖关系,指定文件的编译顺序,以及编译所使用的命令。它和
make
命令使得项目的源程序文件可以自动编译,提高了软件开发效率。到此,再谈一下
make
,它是用来维护程序模块关系和生成可执行程序的工具,它可以根据程序模块的修改情况重新编译链接生成中间代码或最终的可执行程序,省去那些重复的不必要的编译工作,提高编译效率。
Kconfig
给用户提供配置选择的功能。通常配置内核会有四种方法,
make
config
(字符界面配置),
make
menuconfig
(菜单界面配置),
make
xconfig
(依赖
QT
),
make
gconfig
(依赖
GTK+
)。
make
config
比较适合专业人员,像初学者比较适合
make
menuconfig
,让我们重点关注一下它。当我们运行
make
menuconfig
时,配置工具会首先分析与体系结构相对应的
/arch/xxx/Kconfig
文件(
xxx
为传入的
arch
参数),它里面包含了除一些与体系结构相关的配置项和配置菜单外,还通过
source
语句引入了一系列
Kconfig
,配置工具依据这些
Kconfig
包含的菜单和项目就可以描绘出一个分层结构。
例如当我们运行
make
zImagine
、
make
bzImagine
等生成映像的命令时,会先检索顶层的
Makefie
(在
arch/xxx/
目录下的
Makefile
为顶层
Makefile
补充体系结构相关的信息),顶层
Makefile
的两个主要任务是:产生内核映像文件和内核模块。接着顶层
Makefile
会去递归地进入内核的各个子目录,然后分别调用子目录中的
Makefile
(这些
Makefile
记录编译目标),而进入哪些子目录取决于内核的配置。
当使用
make
menuconfig
,
make
config
命令时,生成的
.config
会在源码目录下记录哪些部分被编译入内核,哪些部分被编译为内核模块。简而言之,它是保存内核配置结果的文件。当我们装上
Linux
系统时,第一次查看源码下的所有文件,会发现没有
.config
文件,那是因为从来没配置过内核。当你运行
make
menuconfig
保存并退出时,再次查看就有这个文件了。
配置工具,包括配置命令解释器(对配置脚本中使用的命令进行解释)和配置用户界面(提供字符界面和图形界面),配置工具都是用脚本语言编写的。
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”
,没有被选中。
分享到:
相关推荐
深入linux设备驱动程序内核机制 pdf深入linux设备驱动程序内核机制深入linux设备驱动程序内核机制深入linux设备驱动程序内核机制深入linux设备驱动程序内核机制深入linux设备驱动程序内核机制深入linux设备驱动程序...
Linux内核和设备驱动程序实验报告
Linux内核USB驱动程序框架Linux内核USB驱动程序框架
嵌入式Linux内核及其驱动开发
浅谈 Linux 内核开发之 PCI 设备驱动
linux系统介绍、linux内核组成,分类、linux内核驱动开发流程,常用技巧等。
Linux内核驱动开发详解,基于kernel4.0,对驱动工程师很有帮助
Linux内核与设备驱动程序学习资料笔记+源码.zipLinux内核与设备驱动程序学习资料笔记+源码.zipLinux内核与设备驱动程序学习资料笔记+源码.zipLinux内核与设备驱动程序学习资料笔记+源码.zipLinux内核与设备驱动程序...
Linux内核MTD驱动程序与SD卡驱动程序.doc
Linux设备驱动程序开发简介 Linux设备驱动程序结构 Linux设备驱动程序加载方式 实验:编写一个字符设备驱动程序(LED或蜂鸣器) 分别用静态编译,模块动态加载方法实现加入内核
内容概要 本文深入探讨了Linux设备驱动程序的内核机制,并提供了一个简单的字符设备驱动程序示例。...阅读Linux内核文档和相关书籍,进一步扩展知识面; 对比和学习其他类型的设备驱动程序,拓宽应用领域。
浅谈 Linux 内核开发之 PCI 设备驱动.pdf
LINUX内核经典面试题 ,20) 如何加载、卸载一个模块? 21) 模块和应用程序分别运行在什么空间? 22) Linux中的浮点运算由应用程序实现还是内核实现? 23) 模块程序能否使用可链接的库函数? 24) TLB中缓存的是什么...
Android的Linux内核与驱动程序
学习Linux内核串口驱动的好资料
Linux, linux内核开发,linux驱动开发 包含所有的PPT和WORD文档 注:需要用OpenOffice软件打开
Linux 设备驱动程序开发 精通 [印] Sreekrishnan Venkaveswaran 高清_.pdf Linux 设备驱动 第三版_En_.pdf Linux 设备驱动 第三版_Cn 文字 美 Jonathan Corbet 等_.pdf Linux 内核 深入理解 第三版 En Linux Kernel ...
Linux内核USB主设备驱动程序
linux内核移植与USB驱动开发