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

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需要知道你要的模块是从哪些文件编译生成的,所以你必须通过设置$(-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中定义符号,编写使用说明

Linux内核--在源码树中加入模块_第1张图片
2.png

3、更新Makefile

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

Linux内核--在源码树中加入模块_第2张图片
1.png

4、make menuconfig

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


Linux内核--在源码树中加入模块_第3张图片
3.png

5、最后编译安装内核

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

你可能感兴趣的:(Linux内核--在源码树中加入模块)