[Linux笔记]Linux内核的Makefile和kconfig解读

来源:互联网 发布:vb窗体透明控件不透明 编辑:程序博客网 时间:2024/05/16 15:34
一、概述

       在内核编译中如何将各个目录树中的文件组织起来编译是一个很重要的问题,并且要根据用户配置来编译特有的内核。为了解决这个问题,内核使用两种文件,Makefie和Kconfig。分布到各目录的Kconfig构成了一个分布式的内核配置数据库,每个Kconfig分别描述了所属目录源文档相关的内核配置菜单,就是我们使用命令 make menuconfig(或者xconfig)后产生的配置菜单,此菜单包含多层,每个层次都是由各个目录中的Kconfig产生的。用户根据需求来选择如何编译内核,然后将配置结果保存到.config中,然后执行Makefile时就会根据.config的结果来实现内核的编译。
       这个过程是由kbuild系统来完成的,Linux编译系统会两次扫描Linux的Makefile:首先编译系统会读取Linux内核顶层的Makefile,然后根据读到的内容第二次读取Kbuild的Makefile来编译Linux内核。内核编译系统或者说kbuild,是一种在编译内核时,可以对内核配置选项进行选择的机制。2.6内核树中已经更新了这种机制,新版本的kbuild 不仅高速而且备有更完善的文档。Kbuild机制完全依赖于源代码的层次结构。

二、Makefile文件
       详细说明见:Documentation/kbuild/makefiles.txt
       面对树状结构的内核源码目录,内核编译采用了各个子目录拥有自己目录相关的Makefile(被称为sub-Makefile或kbuild Makefile),内核编译依赖于各个子目录下的子makefile(sub-Makefile)文件,这些sub-Makefile定义了根据该子目录下的源码文件构建目标文件的规则,并且仅对该目录下的文件作适当的修改。顶层Makefile采用递归的方式调用位于init/, drivers/, sound/, net/, lib/ ,usr/等目录下的各个子目录中的 Makefile文件。在递归调用之前,kbuild首先要确定是否已经满足一些必要的条件,包括在必要时更新include/Linux/version.h文件,并设置符号链接include/asm,使之指向与目标体系结构相关的文件。例如,如果为PPC编译代码,则include/asm指向include/asm-ppc。kbuild还要对文件include/Linux/autoconf.h和include/Linux/config进行编译。之后,从根目录开始进行递归。
       各个子Makefile文件比较简单,指出了该如何编译目标文件,例如/mm目录下的Makefile片段:
  16 obj-$(CONFIG_PROC_PAGE_MONITOR) += pagewalk.o
  17 obj-$(CONFIG_BOUNCE)    += bounce.o
  18 obj-$(CONFIG_SWAP)      += page_io.o swap_state.o swapfile.o thrash.o
  19 obj-$(CONFIG_HAS_DMA)   += dmapool.o
  20 obj-$(CONFIG_HUGETLBFS) += hugetlb.o

三、Kconfig文件
       详细说明见:Documentation/kbuild/kconfig-language.txt
       Kconfig的作用就是为了让用户配置内核,在Kconfig中定义了一些变量,用户通过设置变量的值来选择如何个性化自己的系统内核。定义的变量将在每个菜单都有一个关键字标识,最常见的就是config。
语法:
       config symbol
       option "Description"
       symbol是个新的标记的菜单项,options是在这个新的菜单项下的属性和选项
       其中options部分有:
1、类型定义:
       每个config菜单项都要有类型定义,bool布尔类型、 tristate三态:内建、模块、移除 string字符串、 hex十六进制、 integer整型
例如:
menuconfig INPUT_TOUCHSCREEN       <-----------主菜单文件
       default y/N
       bool "Touchscreens"
       help
         Say Y here, and a list of supported touchscreens will be displayed.
         This option doesn't affect the kernel.
         If unsure, say Y.
if INPUT_TOUCHSCREEN
config TOUCHSCREEN_ADS7846
       default y/N
       tristate "ADS7846/TSC2046 and ADS7843 based touchscreens"
       depends on SPI_MASTER
       depends on HWMON = n || HWMON
       help
          Say Y here if you have a touchscreen interface using the 
          ADS7846/TSC2046 or ADS7843 controller, and your board-specific
          setup code includes that in its table of SPI devices.
       bool 类型的只能选中或不选中,tristate类型的菜单项多了编译成内核模块的选项,假如选择编译成内核模块,则会在.config中生成一个 CONFIG_HELLO_MODULE=m的配置,假如选择内建,就是直接编译成内核影响,就会在.config中生成一个 CONFIG_HELLO_MODULE=y的配置.

2、依赖型定义depends on或requires
       指此菜单的出现和否依赖于另一个定义
       config HELLO_MODULE
       bool “hello test module”
       depends on ARCH_PXA
       这个例子表明HELLO_MODULE这个菜单项只对XScale处理器有效。

3、帮助性定义
       只是增加帮助用关键字help或—help—

五、DIY:向内核添加自己的程序
       obj-y:编译进内核中 obj-m:编译成模块
A.在Linux内核中增加自己的程序步骤(注意这里只是程序文件):
  1.将编写的源代码复制到Linux内核源代码的相应目录中。
      2.在目录的Kconfig文件中增加新源代码对应项目的编译配置选项
      3.在目录的Makefile文件中增加对新源代码的编译条目。

B.在Linux内核drivers/目录中增加目录和子目录步骤:
       1.所加目录为myDriver,文件如下:
  myDriver$ tree
  |– Kconfig
  |– Makefile
  |– key
  |   |– Kconfig
  |   |– Makefile
  |   `– key.c
  |– led
  |   |– Kconfig
  |   |– Makefile
  |   `– led.c
  `— test.c
#注意此时各个目录中的Makefile和Kconfig文件是空的

  2.在新增的相应目录添加Kconfig和Makefile文件,上面的目录中已经添加。

  3.修改新增目录的父目录的Kconfig和Makefile文件,以便新增的Kconfig和

  Makefile能被引用。向父目录中的Makefile添加:
  obj-y                           += myDriver/
  表示在编译过程中包含子目录myDriver目录。然后修改Kconfig文件,添加:
  source “drivers/myDriver/Kconfig”
  表示在配置时引用子目录myDriver中的配置文件Kconfig。

  4.经过上面一步,父目录就可以找到所加的目录myDriver了,然后就是编辑各个目 录中的Makefile和Kconfig文件,在你添加的目录myDriver中的Makefile加入:
  obj-$(CONFIG_TEST) += test.o #因为在myDriver目录中要编译test.c文件
  #所以会根据CONFIG_TEST来决定编译选项
  
  如果一个.o由几个文件编译而成,可采用下面的方式:
  If your source spans multiple files, two lines will suffice:
       obj-m := fishing.o
       fishing-objs := fishing-main.o fishing-line.o
       
  obj-y += led/#编译myDriver目录中的子目录led
  obj-y += key/#编译myDriver目录中的子目录key
  然后Kconfig文件是:
  menu “TEST MyDriver”            #在make menuconfig时要显示的菜单入口
  comment “Test myDriver”       #menu title
  config TEST
  tristate “MyDriver test”
  source “drivers/myDriver/led/Kconfig” #将led目录下的Kconfig添加进来
  source “drivers/myDriver/key/Kconfig”
  endmenu
  再看led目录下的Makefile和Kconfig:
  Makefile为文件:
  obj-$(CONFIG_LED)+=led.o
  Kconfig文件:
  config LED
  tristate “led support”
  key目录下的Makefile和Kconfig类似。

  5.现在可以make menuconfig来配置添加自己目录myDriver的内核了!

 

Managing Configuration Options
       An earlier section in this chapter looked at compiling the fishing pole module only if the CONFIG_FISHING_POLE configuration option was set. Configuration options have been discussed in earlier chapters, too, but now let's look at actually adding a new one, continuing with the fishing pole device driver example.Thanks to the new “kbuild” system in the 2.6 kernel, adding new configuration options is easy. All you have to do is add an entry to the Kconfig file responsible for the applicable branch of the kernel source tree. For drivers, this is usually the directory in which the source lives. If the fishing pole driver lives in drivers/char/, you use drivers/char/Kconfig. If you created a new subdirectory and want a new Kconfig file to live there, you need to source it from an existing Kconfig.You do this by adding a line such as the following to an existing Kconfig file:
source “drivers/char/fishing/Kconfig”
       In this example, you would add this line to drivers/char/Kconfig. Entries in Kconfig are easy to add. Our fishing pole module would look like this:
config FISHING_POLE
       tristate “Fish Master 3000 support”
       default n
       help
              If you say Y here, support for the Fish Master 3000 with computer
              interface will be compiled into the kernel and accessible via a
              device node. You can also say M here and the driver will be built as a
              module named fishing.ko.
              If unsure, say N.
       The first line defines what configuration option this entry represents. Note that the CONFIG_ prefix is assumed and not written.
       The second line states that this option is a tristate, meaning that it can be built into the kernel (Y), built as a module (M), or not built at all (N).To remove the option of building as a module—say, if this option represented a feature and not a device driver—use the directive bool instead of tristate.The quoted text following the directive provides the name of this option in the various configuration utilities.
       The third line specifies the default for this option, which is not built (n).You can also specify the default as built into the kernel (y) or built as a module (m). For device drivers, the default is usually to not build it (n).
       The help directive signifies that the rest of the test, indented as it is, is the help text for this entry.The various configuration tools can display this text when requested. Because this text is for developers building their own kernels, it can be succinct and technical. End users do not typically build kernels and, if they did, they could presumably understand the configuration help.
       There are other options, too.The depends directive specifies options that must be set before this option can be set. If the dependencies are not met, the option is disabled. For example, if you added the following directive to the Kconfig entry, the device driver could not be enabled (y or m) until the CONFIG_FISH_TANK option is enabled: 
depends on FISH_TANK
       The select directive is like depends, except that it forces the given option if our option is selected.The select directive should not be used as frequently as depends because it automatically enables other configuration options.The following line enables CONFIG_BAIT whenever CONFIG_FISHING_POLE is enabled:
select BAIT
       For both select and depends, you can request multiple options via &&.With depends, you can also specify that an option not be enabled by prefixing the option with an exclamation mark. For example
depends on EXAMPLE_DRIVERS && !NO_FISHING_ALLOWED
       This line specifies that the driver depends on CONFIG_EXAMPLE_DRIVERS being set and CONFIG_NO_FISHING_ALLOWED being unset.
       The tristate and bool options can be followed by the directive if, which makes the entire option conditional on another configuration option. If the condition is not met, the configuration option is not only disabled but also does not appear in the configuration utilities. For example, this directive instructs the configuration system to display an option only if CONFIG_OCEAN is set. Here, deep sea mode is available only if CONFIG_OCEAN
is enabled:
bool “Deep Sea Mode” if OCEAN
       The if directive can also follow the default directive, enforcing the default only if the conditional is met.
       The configuration system exports several meta-options to help make configuration easier.The option CONFIG_EMBEDDED is enabled onl

原创粉丝点击