linux驱动开发学习笔记八:配置内核必不可少的工具--menuconfig

一、常见的几种配置工具介绍

在配置内核的时候会有很多配置方法:

  • make menuconfig
  • make xxx_defconfig
  • 直接修改.config

注意: 其中menuconfig是一个图形化配置工具,在后面我们会着重介绍;xxx_defconfig是在arch/arm/configs文件夹下的一些默认配置文件;.config是编译的时候系统默认读取的配置文件,如果直接修改.config,不一定会生效,因为有些配置可能存在依赖关系,make时会根据依赖关系,进行规则的检查,直接修改.config有时无效,所以不推荐直接修改。

通过以上我们也可以知道,如果想要使用默认配置文件,也即xxx_defconfig,那么我们除了可以直接执行·make xxx_defconfig·,还可以直接把xxx_defconfig里的内容复制到我们的.config文件中,这样make的时候不用加配置文件就可以自动去读取.config配置文件。

menuconfig及其类似的几款配置工具:

  • make config(基于文本的最为传统的配置界面,不推荐使用)
  • make menuconfig(基于文本选单的配置界面,字符终端下推荐使用)
  • make xconfig(基于图形窗口模式的配置界面,Xwindow下推荐使用)
  • make oldconfig(如果只想在原来内核配置的基础上修改一些小地方,这种方法会省去不少麻烦)

以上四种配置方法它们的目的都是生成一个.config文件,这几个命令中,make xconfig的界面最为友好,如果你可以使用Xwindow,你就用这个好了,这个比较方便,也好设置;如果你不能使用Xwindow,那么就使用make menuconfig好了,界面虽然比上面一个差点,但是比另外两个方法要好多了。

二、menuconfig工具介绍

1、简介

menuconfig是一套图像化配置工具,由ncurses库提供软件支持。ncurses库提供了一系列的函数以便使用者调用它们去生成基于文本的用户界面。menuconfig本身的软件只负责提供menuconfig工作的这一套逻辑,比如说通过上下左右调整光标,Enter选中等,并不负责提供内容。

menuconfig运行之后会读取Kconfig文件、读取/写入.config文件,Kconfig文件提供菜单项的内容,.config用来记录菜单项的选择值。

2、可选的三种编译方法

linux内核中一个功能模块有三种编译方法:一种是编入、一种是去除、一种是模块化。在进行配置的时候对应着有三种选择:

  • Y-将该功能编译进内核

  • N-不将该功能编译进内核

  • M-将该功能编译成可以在需要时动态插入到内核中的模块

所谓编入就是将这个模块的代码直接编译链接到zImage中去,去除就是将这个模块不编译链接到zImage中,模块化是将这个模块仍然编译,但是不会将其链接到zImage中,会将这个模块单独链接成一个内核模块.ko文件,将来linux系统内核启动起来后可以动态的加载或卸载这个模块。

3、每条选项前面的[ ]、< >、()的意思

menuconfig中选项前面的括号里,*表示编入,空白表示去除,M表示模块化。

  • [ ]:只有编入和去除两种状态,也即此选项不可以模块化

  • < >:三种编译状态都有

  • ( ):存放十进制或十六进制或字符串;

二、menuconfig配置界面的打开方法

其实打开方式很简单,但是我之前还是踩了坑,我们只需要执行make menuconfig即可。但是该命令执行的位置是需要特别注意的,不是直接在根目录下执行,而是找到你下载的linux内核源码,然后在arch文件夹所在的同级路径下打开命令行输入make menuconfig。如果缺少一些依赖库,可以根据错误去安装,这里就不说了。

三、Kconfig文件语法

前面我们也说了,menuconfig运行之后会读取Kconfig文件、读取/写入.config文件,Kconfig文件提供菜单项的内容,.config用来记录菜单项的选择值。其实Kconfig我们也可以看作一个编程语言,那么Kconfig文件我们应该怎么编写呢?它又有哪些语法和规则呢?

kconfig的总入口是arch/arm/kconfig,不是源码顶层的kconfig,因为入口一定是具体对应某一款平台的。

1.tristate、bool、string

  • bool:表示有两种状态,选项前会有[ * ]/[ ],分别代表编入和去除
  • tristate:表示有三种状态,选项前会有< * >/< >/< M > ,分别代表编入、去除、编译成模块
  • string:表示这是十进制或者十六进制或者字符串,选项前会有( ),括号里有相应的内容

2.mainmenu

如果在配置界面选择了它,那么就用它配置标题栏,也即它后面的字符串会显示在配置界面的标题栏中。

mainmenu "Linux Kernel Configuration"

config ARM
	bool
	default y
	select HAVE_AOUT
	select HAVE_IDE

3.config

开启一个新的配置选项入口,下面的行定义了配置选项的属性,属性可以是配置输入提示、依赖、帮助文档和默认值等,一个配置选项可以被多次定义,但是每一次定义只有单一的输入提示,并且类型不能冲突。

config MODVERSIONS
	bool "Set version information on all module symbols"
	depends on MODULES
	help
	  Usually, modules have to be recompiled whenever you 
	  switch to a newkernel.

4.prompt

输入提示作用,下面两种方式,效果相同。

bool "Networking support"
bool
prompt "Networking support"

5.depends on、select

depends on表示此选项会依赖其它选项的配置,也就是depends on后面指定的选项被选择之后,该选项才能被选择;select表示反向依赖,如果当前项选中,那么也选中select后指定的选项。

6.default

用于设定默认值,y表示该选项默认被选择上。

7.menu

定义一个菜单入口, 表示Network device support是一个菜单选项。菜单选项不是一个功能,也即config 后面的指定的功能选项,它只是表示只有进入这个菜单里面,才能去配置里面的功能选项。

menu "Network device support"
	depends on NET

config NETDEVICES
	...
endmenu

8.source

将另外一个Kconfig文件直接复制到当前位置,可以将整个系统贯穿在一起,也可以使我们避免重复写一些内容。假如我在linux-4.1.15/drivers/下新建了一个hello文件夹,用来保存我新写的hello world驱动程序,那么在linux-4.1.15/drivers/hello下肯定要有一个Kconfig文件,此时我们就需要在上一级的,也就是linux-4.1.15/drivers/下的Kconfig文件中添加一句source "drivers/hello/Kconfig"

config test
	bool
	help
	  Setting ARM L1 cache line size to 64 Bytes.

source "arch/arm/Kconfig"

9.help

帮助信息,告诉我们这个配置项的含义,以及如何去配置他。

剩下的一些语法就需要我们自己不断的积累和查找资料了,这里就不一个一个的说了。

四、配置过程中涉及到的几个主要的文件

  • Kconfig
  • Makefile
  • .config

它们之间的关系如下:

  • 我们通过编写Kconfig在配置菜单上添加所需的配置项
  • 配置项被配置成Y、N、M会影响.config文件中的CONFIG_XXX变量的值。
  • .config中的配置值(=y、=m、=n)会影响最终的编译链接过程。如果=y则会被编入,如果=m会被单独连接成一个.ko模块,如果=n则对应的代码不会被编译。而编译与不编译就是makefile根据CONFIG_XXX变量的值来决定的。

假如我们添加了一个test功能项,配置好之后这三个文件里的相关内容如下:

  • Kconfig中:config test

  • makefile中:obj-$(test) += xxxxx.c

  • .config中:CONFIG_test=y

五、举个例子来演示一下将驱动编译进内核的过程

假如我写了一个简单的在入口函数中输出hello world的驱动并编译进内核。那么整个步骤大概是这样的:

1、在drivers目录下新建hello文件夹,里面实现hello.c、Makefile、Kconfig。

hello.c

#include <linux/module.h>  

#include <linux/kernel.h> 

#include <linux/init.h>  

static int first_drv_init(void)  

{ 

  printk("------------------hello world !--------------------"); 

   return 0;  

} 

static void first_drv_exit(void) 

{  

   printk("------------------exit hello world!--------------------"); 

}  

module_init(first_drv_init); 

module_exit(first_drv_exit); 

MODULE_LICENSE("GPL");

Makefile

obj-$(CONFIG_HELLO)  += hello.o

Kconfig:

config HELLO  

   tristate "Hello Worldfor fengyuwuzu"  

   help  

     Hello  forfengyuwuzu  

config HELLO决定名字:CONFIG_HELLO。
Hello World for fengyuwuzu:决定了在make menuconfig时显示的名字

2、修改上一级(linux-4.1.15/drivers下)的Makefile、Kconfig

Makefile:

obj-y  += hello/  

Kconfig:

source "drivers/hello/Kconfig"  
3、make menuconfig

在这里插入图片描述

4、编译成zimage和相关文件,然后烧写到开发板

查看内核启动Log,helloworld 出来了就说明hello.c成功编进内核
在这里插入图片描述

六、结语

至此,关于menuconfig我想说的已经说得差不多了,重要的在于理清思路,具体的一些细节肯定还需要我们自己去查资料和总结。

参考文章1:浅谈内核的Makefile、Kconfig和.config文件

参考文章2:嵌入式Linux–menuconfig详解

猜你喜欢

转载自blog.csdn.net/qq_39507748/article/details/105781939