1. Linux内核的编译
Linux 驱动开发者需要牢固地掌握Linux 内核的编译方法以为嵌入式系统构建可运行的Linux 操作系统映像。在编译内核时,需要配置内核,可以使用下面命令中的一个:
#make config (基于文本的最为传统的配置界面,不推荐使用)
#make menuconfig (基于文本菜单的配置界面, 推荐使用)
#make xconfig (要求QT被安装)
运行make menuconfig 等时,配置工具首先分析与体系结构对应的/arch/xxx/Kconfig 文件(xxx 即为传入的ARCH 参数),/arch/xxx/Kconfig 文件中除本身包含一些与体系结构相关的配置项和配置菜单以外,还通过source 语句引入了一系列Kconfig 文件,而这些Kconfig又可能再次通过source 引入下一层的Kconfig,配置工具依据Kconfig 包含的菜单和条目即可描绘出一个如图3的分层结构。
2. Kconfig 和 Makefile
在Linux 内核中增加程序需要完成以下3 项工作。
● 将编写的源代码复制到 Linux 内核源代码的相应目录中。
● 在目录的 Kconfig 文件中增加关于新源代码对应项目的编译配置选项。
● 在目录的 Makefile 文件中增加对新源代码的编译条目。
2.1. 实例引导:TTY_PRINTK 字符设备
在讲解Kconfig 和Makefile 的语法之前,我们先利用两个简单的实例引导读者对其建立对具初步的认识。
首先,在drivers/char 目录中包含了TTY_PRINTK 设备驱动的源代码drivers/char/ttyprintk.c。而在该目录的Kconfig 文件中包含关于TTY_PRINTK 的配置项:
config TTY_PRINTK
tristate "TTY driver to output user messages via printk"
depends on EXPERT && TTY
default n
---help---
If you say Y here, the support for writing user messages (i.e.
console messages) via printk is available.
The feature is useful to inline user messages with kernel
messages.
In order to use this feature, you should output user messages
to /dev/ttyprintk or redirect console to this TTY.
If unsure, say N.
上述Kconfig 文件的这段脚本意味着只有在EXPERT 和TTY 被配置的情况下,才会出现TTY_PRINTK 配置项,这个配置项为三态(可编译入内核,可不编译,也可编译为内核模块,选项分别为“ Y”、“ N”和“ M”),菜单上显示的字符串为“ TTY driver to output user messages via printk ”,“ help”后面的内容为帮助信息。显示了TTY_PRINTK 菜单以及help 在运行make menuconfig 时的情况。
除了布尔(bool)配置项外,还存在一种布尔配置选项,它意味着要么编译入内核,要么不编译,选项为“Y”或“N”。
在目录的Makefile 中关于TTY_PRINTK 的编译项为:
obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o
上述脚本意味着如果TTY_PRINTK 配置选项被选择为“ Y”或“M”,即obj-$(CONFIG_TTY_PRINTK) 等同于obj-y 或obj-m,则编译ttyprintk.c,选“Y”时会直接将生成的目标代码连接到内核,选“ M”时则会生成模块ttyprintk.ko ;如果TTY_PRINTK 配置选项被选择为“N”,即obj-$(CONFIG_TTY_PRINTK) 等同于obj-n,则不编译ttyprintk.c。
一般而言,驱动开发者会在内核源代码的drivers 目录内的相应子目录中增加新设备驱动的源代码或者在arch/arm/mach-xxx 下新增加板级支持的代码,同时增加或修改Kconfig 配置脚本和Makefile 脚本,具体执行完全仿照上述过程即可。
2.2 Makefile
这里主要对内核源代码各级子目录中的kbuild(内核的编译系统)Makefile 进行简单介绍,这部分是内核模块或设备驱动开发者最常接触到的。
Makefile 的语法包括如下几个方面。
(1)目标定义
目标定义就是用来定义哪些内容要作为模块编译,哪些要编译并链接进内核。
例如:
obj-y += fingerprint.o
表示要由fingerprint.c 或者fingerpint.s 文件编译得到fingerprint.o 并链接进内核(无条件编译,所以不需要Kconfig 配置选项),而obj-m 则表示该文件要作为模块编译。obj-n 形式的目标不会被编译。
更常见的做法是根据make menuconfig 后生成的config 文件的CONFIG_ 变量来决定文件的编译方式,如:
obj-$(CONFIG_ISDN) += isdn.o
obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o