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詳解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章