一 . 概述:

  在 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 命令时,生成的nfig 会在源码目录下记录哪些部分被编译入内核,哪些部分被编译为内核模块。简而言之,它是保存内核配置结果的文件。当我们装上 Linux 系统时,第一次查看源码下的所有文件,会发现没有nfig 文件,那是因为从来没配置过内核。当你运行 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) 我们最常用的的做法是根据nfig 文件的 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内核开发之将驱动程序添加到内核相关推荐

  1. 嵌入式Linux驱动开发 02:将驱动程序添加到内核中

    文章目录 目的 基础说明 添加到内核中 Kconfig Makefile 驱动程序 编译与测试 模块方式 编译到内核中 总结 目的 在上一篇文章 <嵌入式Linux驱动开发 01:基础开发与使用 ...

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

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

  3. USB转WIFI无线网卡驱动程序(内核自带RT5370驱动程序添加)的移植记录之二

    学习交流加 个人qq: 1126137994 个人微信: liu1126137994 学习交流资源分享qq群: 962535112 今天记录我在I.MX6Q平台添加内核自带RT5370无线网卡驱动程序 ...

  4. Linux驱动开发必看详解神秘内核

    I 在开始步入Linux设备驱动程序的神秘世界之前,让我们从驱动程序开发人员的角度看几个内核构成要素,熟悉一些基本的内核概念.我们将学习内核定时器.同步机制以及内存分配方法.不过,我们还是得从头开始这 ...

  5. Linux 内核学习知识:浅析 offsetof 宏以及内核开发学习的所思所想(内核开发人员必读)

    最近一头扎进了 Linux 内核的学习中,Linux 内核的学习,需要的基础知识太多太多了:C 语言.汇编语言.数据结构与算法.操作系统原理.计算机组成原理.计算机体系结构.在囫囵吞枣补完一些计算机基 ...

  6. linux找不到网络打印机驱动程序,添加网络打印机时提示找不到驱动程序

    原标题:"添加网络打印机,小编教你如何添加网络打印机"关于电脑问题教程分享. - 来源:191路由网 - 编辑:小元. 如今我们在工作和学习之中,经常会用到打印机,现在我们一般做一 ...

  7. 如何参与linux内核开发

    来源: http://www.cnblogs.com/amaoxiaozhu/p/3340733.html 如果想评论或更新本文的内容,请直接联系原文档的维护者.如果你使用英文 交流有困难的话,也可以 ...

  8. 如何参与linux 内核开发

    如何参与linux 内核开发 原文链接:http://www.cnblogs.com/amaoxiaozhu/p/3340733.html 如果想评论或更新本文的内容,请直接联系原文档的维护者.如果你 ...

  9. 理解Linux内核漏洞:(内核开发人员必读)

    初步理解内核漏洞:(内核开发人员必读) 内核开发人员,如果不了解内核漏洞的话,容易在开发时引入漏洞,轻则导致内核崩溃,影响上面的所有应用程序:重则导致内核提权,即可以突破应用层的沙箱,进入内核,并在内 ...

最新文章

  1. 环保—北京周边 自行车骑行线路大全
  2. Lua coroutine 不一样的多线程编程思路
  3. MS SQL 2008 发布订阅配置错误总结
  4. 开源的,跨平台的.NET机器学习框架ML.NET
  5. FreeRTOS中断配置与临界段
  6. css样式变 及实际用法
  7. 贪心算法,递归算法,动态规划算法比较与总结
  8. php 二进制 十六进制转换,php 实现进制转换(二进制、八进制、十六进制)互相转换实现代码...
  9. 汇编观察a++和++a
  10. 家庭网关斐讯 K3 基础环境篇
  11. Html转Word解决转存图片时候的跨域问题、默认打开视图问题
  12. “剧情+综艺” 助推国潮文化破圈
  13. Arduino ESP32 Web网页控制RGB灯
  14. 自动化行业软件工程师工作第一年总结
  15. 手把手教你创建群晖nas「共享文件夹」,从此告别 U 盘和低效传输
  16. html改变元素外边距,CSS 简明教程 - 外边距 ( margin ) 属性
  17. 盛大创新院创新模式梳理
  18. orb-slam2 从单目开始的简单学习(7):Optimizer
  19. 天池学习赛 -【零基础入门语音识别-食物声音识别】Task1 食物声音识别-Baseline【代码详细手写解释】
  20. vue-router使用详解

热门文章

  1. css3宽度变大动画_不会仪表?太尴尬了。14种动画让你轻松掌握各种流量计工作原理...
  2. oracle+数据到+mysql数据库乱码问题_Linux系统Oracle数据库乱码问题的解决方法
  3. 关于文件格式和编码方式,乱码产生的原因?
  4. linux导出并追加到文件,linux – 如何将awk结果输出到文件
  5. Java数据结构和算法:字符串、数组和广义表
  6. Wireshark网络抓包实践
  7. web项目html页面过多,详解webpack4多入口、多页面项目构建案例
  8. 如果常数项没有经过显著性检验_Cg,Cgk 能代替偏倚显著性检验?
  9. Zabbix5.0监控系统安装详解
  10. 分布式图处理系统同步异步执行模式