一、常見的幾種配置工具介紹
在配置內核的時候會有很多配置方法:
- 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詳解