驱动程序添加到内核

一.概述:

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

sudogedit 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"

defaultn

help

Ifyou say Y here,support for the usbtmc with computer interface will becompiled 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.

Ifunsure,say N.

endmenu

endmenu

正确配置好后,我们在源码下执行sudomake menuconfig后,在出现的LinuxKernel Configuration图形界面中选择DeviceDrivers下的characterdevcie中,将会看到新加的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下的characterdevices里可以找到USBTMC)对其进行选定。然后退出,编译内核,就搞定了。

5.删除:

删除也很简单,首先在drivers/char目录下删掉自己的驱动文件夹。其次再删除Makefile和Kconfig之前添加的东西,就搞定了

三.详解:

Makefile,Kconfig和配置工具组成了Linux2.6内核的配置系统。
其中Makefile定义了Linux内核的编译规则,它是大型项目开发的产物。Linux环境下的大型项目开发中,系统被分为很多模块,而这些模块一般会经历几次修改,而在修改后的编译过程中,由于某些文件中存在依赖关系,人工编译效率低(有些文件不需要重新编译)且易出错,Makefile文件便应运而生。Makefile文件定义了模块间的依赖关系,指定文件的编译顺序,以及编译所使用的命令。它和make命令使得项目的源程序文件可以自动编译,提高了软件开发效率。到此,再谈一下make,它是用来维护程序模块关系和生成可执行程序的工具,它可以根据程序模块的修改情况重新编译链接生成中间代码或最终的可执行程序,省去那些重复的不必要的编译工作,提高编译效率。
Kconfig给用户提供配置选择的功能。通常配置内核会有四种方法,makeconfig(字符界面配置),makemenuconfig(菜单界面配置),makexconfig(依赖QT),makegconfig(依赖GTK+)。makeconfig比较适合专业人员,像初学者比较适合makemenuconfig,让我们重点关注一下它。当我们运行makemenuconfig时,配置工具会首先分析与体系结构相对应的/arch/xxx/Kconfig文件(xxx为传入的arch参数),它里面包含了除一些与体系结构相关的配置项和配置菜单外,还通过source语句引入了一系列Kconfig,配置工具依据这些Kconfig包含的菜单和项目就可以描绘出一个分层结构。
例如当我们运行makezImagine、makebzImagine等生成映像的命令时,会先检索顶层的Makefie(在arch/xxx/目录下的Makefile为顶层Makefile补充体系结构相关的信息),顶层Makefile的两个主要任务是:产生内核映像文件和内核模块。接着顶层Makefile会去递归地进入内核的各个子目录,然后分别调用子目录中的Makefile(这些Makefile记录编译目标),而进入哪些子目录取决于内核的配置。
当使用makemenuconfig,makeconfig命令时,生成的.config会在源码目录下记录哪些部分被编译入内核,哪些部分被编译为内核模块。简而言之,它是保存内核配置结果的文件。当我们装上Linux系统时,第一次查看源码下的所有文件,会发现没有.config文件,那是因为从来没配置过内核。当你运行makemenuconfig保存并退出时,再次查看就有这个文件了。
配置工具,包括配置命令解释器(对配置脚本中使用的命令进行解释)和配置用户界面(提供字符界面和图形界面),配置工具都是用脚本语言编写的。

1.在进入menuconfig配置界面时,会发现每个配置项目为布尔型(要么编译入内核,要么不编译,选项为“Y”或“N”),菜单上为配置选项的名字例如:“XXXDriver”,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

对内核源代码各级子目录中的kbuildMakefile进行介绍,

(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)依赖关系的格式如下所示:

dependson (或者 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”

dependson NET

config NETDEVICES

endmenu

所有处于”menu”和”endmenu”之间的菜单入口都会成为“Networkdevice support”的子菜单。而且,所有子菜单选项都会继承父菜单的依赖关系,比如:“Networkdevice 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”

dependson MODULES

comment “module support disabled”

depends on !MODULES

MODVERSIONS直接依赖MODULES,如果MODULES不为“N”,该选项才可见。

(3)除此之外,Kconfig中还可能使用“choices…...endchoice”,”comment”,”if....endif”这样的语法结构。

其中

choice

<choiceoptions>

<choiceblock>

enchoice

它定义一个选择群,其接受的选项(choiceoptions)可以是前面描述的任何属性。在一个硬件有多个驱动的情况下使用,使用选择可以实现最终只有一个驱动被编译进内核或模块。选择群还可以接受的另一个选项是“optional”,

这样菜单入口就被设置为“N”,没有被选中。

Linux内核开发之将驱动程序添加到内核的更多相关文章

  1. Linux驱动开发必看详解神秘内核(完全转载)

    Linux驱动开发必看详解神秘内核 完全转载-链接:http://blog.chinaunix.net/uid-21356596-id-1827434.html   IT168 技术文档]在开始步入L ...

  2. 如何参与Linux内核开发(转)

    本文来源于linux内核代码的Document文件夹下的Hoto文件.Chinese translated version of Documentation/HOWTO If you have any ...

  3. 如何参与linux 内核开发

    如果想评论或更新本文的内容,请直接联系原文档的维护者.如果你使用英文 交流有困难的话,也可以向中文版维护者求助.如果本翻译更新不及时或者翻 译存在问题,请联系中文版维护者.   英文版维护者: Gre ...

  4. 如何参与linux内核开发

    如何参与linux 内核开发   如果想评论或更新本文的内容,请直接联系原文档的维护者.如果你使用英文 交流有困难的话,也可以向中文版维护者求助.如果本翻译更新不及时或者翻 译存在问题,请联系中文版维 ...

  5. Windows内核开发-2-开始内核开发-2-内核开发入门

    Windows内核开发-2-开始内核开发-2- 第一个驱动程序: 直接采用vs2019中的Empty WDM Driver 模块创建: 初始的项目文件夹中有一个Driver Files里面会有一个.i ...

  6. Linux内核启动代码分析二之开发板相关驱动程序加载分析

    Linux内核启动代码分析二之开发板相关驱动程序加载分析 1 从linux开始启动的函数start_kernel开始分析,该函数位于linux-2.6.22/init/main.c  start_ke ...

  7. 嵌入式系统Linux内核开发工程师必须掌握的三十道题(转)

    嵌入式系统Linux内核开发工程师必须掌握的三十道题 如果你能正确回答以下问题并理解相关知识点原理,那么你就可以算得上是基本合格的Linux内核开发工程师,试试看! 1) Linux中主要有哪几种内核 ...

  8. Linux 内核开发—内核简单介绍

    内核简单介绍 Linux 构成 Linux 为什么被划分为系统空间和内核空间 隔离核心程序和应用程序,实现对核心程序和数据的保护. 什么内核空间,用户空间 内核空间和用户空间是程序执行的两种不同的状态 ...

  9. Linux内核(17) - 高效学习Linux驱动开发

    这本<Linux内核修炼之道>已经开卖(网上的链接为: 卓越.当当.china-pub ),虽然是严肃文学,但为了保证流畅性,大部分文字我还都是斟词灼句,反复的念几遍才写上去的,尽量考虑到 ...

随机推荐

  1. Notepad++运行Java

    插件NppExec使用 首先要让Notepad++编译和运行Java,前提是电脑里已经配置好了Java的环境 1,安装插件NppExec:解压出来提取NppExec.dll文件放在Notepad++安 ...

  2. Object Detection · RCNN论文解读

    转载请注明作者:梦里茶 Object Detection,顾名思义就是从图像中检测出目标对象,具体而言是找到对象的位置,常见的数据集是PASCAL VOC系列.2010年-2012年,Object D ...

  3. 玩转webpack(二):webpack的核心对象

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者介绍:陈柏信,腾讯前端开发,目前主要负责手Q游戏中心业务开发,以及项目相关的技术升级.架构优化等工作. 前言 webpack 是一个强大的模 ...

  4. OpenStack和Hadoop的区别

    其实,OpenStack和Hadoop不是同一个层次的东西,无法比较,非要说出个区别,那就是:OpenStack是云计算管理平台,应该是属于系统级别的软件,它的主体思想是把资源进行分离,给不同的用户提 ...

  5. 关于css选择器的一些细节

    1.如何区分一个html标签的不同样式 使用标签名.类名的方式解决 如果希望特别强调其中的某一个或几个元素,处理的方案有三个: 1.id选择器 2.class选择器 3.层级选择器 看下面的代码: & ...

  6. IO模型浅析

    IO模型 同步.异步.阻塞.非阻塞 同步: 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回.也就是必须一件一件事做,等前一件做完了才能做下一件事. 例如普通B/S模式(同步): ...

  7. 修改Java程序的进程名

    1.修改tomcat进程名字: 当同一个服务器上启动多个tomcat后,我们会在任务管理器中看见多个java.exe,当我们需要对某个tomcat进行监控时,却无法区分出该tomcat的进程,那么如何 ...

  8. BZOJ 3620: 似乎在梦中见过的样子 [KMP 暴力]

    和我签订契约,成为魔法少女吧 题意:求所有形似于A+B+A 的子串的数量 , 且len(A)>=k,len(B)>=1 位置不同其他性质相同的子串算不同子串,位置相同但拆分不同的子串算同一 ...

  9. BZOJ 2882: 工艺 [后缀自动机+map]

    Description 小敏和小燕是一对好朋友. 他们正在玩一种神奇的游戏,叫Minecraft. 他们现在要做一个由方块构成的长条工艺品.但是方块现在是乱的,而且由于机器的要求,他们只能做到把这个工 ...

  10. A 洛谷 P3601 签到题 [欧拉函数 质因子分解]

    题目背景 这是一道签到题! 建议做题之前仔细阅读数据范围! 题目描述 我们定义一个函数:qiandao(x)为小于等于x的数中与x不互质的数的个数. 这题作为签到题,给出l和r,要求求. 输入输出格式 ...