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;其它的类型都是基于这两种属性的。
其它
操作步骤
1、源代码放在合适的位置。
比如有关wifi的驱动放在drivers/net/wireless
把sc.c放入/dev/character
2、更新Kconfig
在Kconfig中定义符号,编写使用说明
3、更新Makefile
这样你的代码可以编译进你的系统。
4、make menuconfig
更改相应的选项:比如在Drevice Drivers > character devices中更改:
5、最后编译安装内核
参考Ubuntu-Linux内核更新,这样你的自己编写的内核文件,就能编译内核中了。