美文网首页首页投稿(暂停使用,暂停投稿)
Linux内核--在源码树中加入模块

Linux内核--在源码树中加入模块

作者: shenyifu | 来源:发表于2016-05-17 11:19 被阅读397次

    kbuild

    为了能够清楚的说明这一部分我们先来说一下kbuild。内核中的大多数Makefiles是使用kbuild基本语法规则的kbuild Makefiles。这一章介绍kbuild makefiles的语法。

    kbuild文件的首选名字是'Makefile',但是'Kbuild'也可以使用。如果'Makefile'和'Kbuild' 文件同时存在,那么'Kbuild'文件将会被使用。

    目标定义

    目标定义是kbuildMakefile文件的主要部分(核心),它们定义了将要被构建的文件,任何具体的编译选项,以及任何将要递归进入的子目录。
    最简单的kbuild makefile只包含一行:

    obj-y += foo.o
    

    这一行告诉kbuild这个目录只有一个叫做foo.o的的目标。foo.o将从foo.c或者foo.S生成。

    如果foo.o将被生成为一个模块,那么就使用obj-m变量。因此下面的模版经常会被使用:

    obj-$(CONFIG_FOO) += foo.o
    

    $(CONFIG_FOO)等于y(编译进内核)或者m(编译为模块)。如果$(CONFIG_FOO)既不是y也不是m,那么这个文件就不会被编译也不会被链接。

    编译进内核的目标对象 - obj-y

    KbuildMakefile在$(obj-y)列表中指定了编译进vmlinux的对象文件。这个列表依靠内核配置文件生成。

    Kbuild编译所有的$(obj-y)文件。然后调用"$(LD)-r"将这些编译生成的文件合成到一个built-in.o文件中。Built-in.o稍后会被父层Makfile链接到vmlinux中。

    $(obj-y)列表中文件的顺序是有意义的。文件可以在$(obj-y)列表中重复,但是只有第一个出现的文件会被编译到built-in.o中,而接下来出现的重复文件会被忽略。

    链接顺序也是有意义的。因为某些函数(比如(module_init() / __initcall))在系统启动的过程中将会按照它们出现的顺序调用。所以记住改变链接顺序将会造成一些不确定情况。

    可加载模块目标 - obj-m

    $(obj-m) 指定一个目标文件将会被编译为一个可加载的内核模块。

    一个模块可以由一个或者多个源文件编译生成。对于模块由一个源文件生成的情况,kbuild makefile只需要简单地将源文件加入到$(obj-m)列表。

    obj-$(CONFIG_ISDN_PPP_BSDCOMP)+= isdn_bsdcomp.o
    

    注意:这个例子中$(CONFIG_ISDN_PPP_BSDCOMP)变量的值等于’m’。

    如果一个内核模块由多个源文件编译而成,你需要像上面例子一样指定需要生成的模块。

    Kbuild需要知道你要的模块是从哪些文件编译生成的,所以你必须通过设置$(<module_name>-objs)变量来让Kbuild知道。

    其它

    其实kbuild的语法相当复杂,本文不做过多讨论,英文文档请参考:linux内核源码树
    的/Documentation/kbuild下的说明,比较好的中文翻译: linux官方文档翻译 -- Makefile的语法,感谢翻译人员的辛勤工作。

    kconfig

    菜单入口

    大多数入口在Kconfig文件中都定义了一个配置选项;所有其它的入口都用来组织这些配置选项。一个典型的配置选项是这样定义的:

    config MODVERSIONS
           bool"Set version information on all module symbols"
           dependson MODULES
           help
             Usually, modules have to be recompiledwhenever you switch to a new
             kernel. ...
    

    每一行都以一个关键字开头,并且后面可以跟多个参数。一个新的配置入口是以“config”关键字开始的。接下来的数行是对这个配置选项的属性定义。属性可以是类型、输入提示、依赖项、帮助文档以及默认值。一个配置选项用相同的名字定义多次,但是每次定义的输入提示和类型都必须不一样。

    菜单属性

    一个菜单入口可以有多个属性。不是所有的属性在任何地方都会有效。

    • 类型定义:"bool"/"tristate"/"string"/"hex"/"int"
      每个配置选项必须都有一个类型。在上面这几个类型中其实只有两个基本类型:tirstate和string;其它的类型都是基于这两种属性的。

    其它

    请参考linux官方文档翻译--Kconfig的语法

    操作步骤

    1、源代码放在合适的位置。

    比如有关wifi的驱动放在drivers/net/wireless
    把sc.c放入/dev/character

    2、更新Kconfig

    在Kconfig中定义符号,编写使用说明

    2.png

    3、更新Makefile

    这样你的代码可以编译进你的系统。

    1.png

    4、make menuconfig

    更改相应的选项:比如在Drevice Drivers > character devices中更改:


    3.png

    5、最后编译安装内核

    参考Ubuntu-Linux内核更新,这样你的自己编写的内核文件,就能编译内核中了。

    相关文章

      网友评论

        本文标题:Linux内核--在源码树中加入模块

        本文链接:https://www.haomeiwen.com/subject/sykirttx.html