Linux內核的配置:menuconfig和Kconfig和.config和Makefile的關係

一、配置前先確認Makefile來檢查交叉編譯工具鏈和SoC架構有沒有設置對。
CROSS_COMPILE ?= 交叉編譯工具鏈的安裝目錄
ARCH = SOC的 架構,比如arm,主要目的是爲了編譯時能找到arch/arm目錄。

二、內核配置,分二步
(1)第一步配置 make xxx_defconfig
xxx文件和具體的開發板相對應,若是ARM架構的話,在arch/arm/configs/目錄下, 這一步其實就是把arch/arm/configs/目錄下的xxx文件中的內容,複製到生成的 .config文件中(arch/arm/configs目錄下的這麼多個xxx_defconfig哪裏來的?其實這些文件都是別人手工配置好適合一定的開發板的.config文件後自己把.config文件保存過去的。針對這個SoC的開發板的最初配置肯定是SoC原廠的工程師去做的)。
若最後只要出現:configuration written to .config證明我們的配置成功。通過這一步配置ls -a命令便可以看到.config隱藏文件。配置的關鍵就是得到.config文件,可以說內核的整個配置過程就是圍繞.config來展開的。其作用類似與uboot中的include/configs/目錄下的xxx.h文件(uboot便是利用它完成配置的),內核在編譯過程中會讀取生成的.config文件中的配置項,並且用這些配置項去指導整個編譯鏈接過程。
打開.config文件便可發現,它的格式類似於腳本文件,其中內容是一行一行的配置項和配置值,隨便抽取一行CONFIG_ARM=y。這樣的配置值有兩三千行,由此可見linux內核是高度可配置的。正是因爲linux內核的配置項太多太繁雜了,因此linux內核不能再像uboot那樣直接手工配置,而是發明了一個圖形化的配置工具menuconfig,來降低配置難度。當然你的大腦足夠厲害能夠記住這二三千行的話,你每次可直接在.config文件中手動書寫/修改.config文件完成內核配置,最終只要.config中內容是正確的,就不影響編譯過程。呵呵
(2) 第二步配置make menuconfig
這步操作一定要確保Ubuntu安裝了ncurses庫,因爲ncurses庫是linux中用來實現文字式的圖形界面(執行make menuconfig後從顯示的的配置信息就可以看出scripts\kconfig\lxdialog目錄下的一些c文件就是用來提供menuconfig的那些程序源代碼),另外還要保證中段控制檯屏幕全屏,否則可能顯示不出圖形化界面。
menuconfig讀取第一步得到的.config文件和Linux中的Kconfig文件,用.config文件中的配置選擇結果來初始化menuconfig中各個菜單項的選擇值最終給我們一個圖形化的界面,讓我們可以更加容易的找到自己想要修改的配置項,然後更改配置它。如下圖所示,可以發現menuconfig中間的選擇區中有很多個選擇項,每個選擇項對應.config文件中的一個配置項,將光標放在選擇項上按Enter鍵可以進入子目錄( —>的選項纔是有子菜單的);;按鍵Y、N、M三個按鍵的作用分別是將選中模塊編入、去除、模塊化;雙擊ESC表示退出;按鍵?可以顯示幫助信息;按下/按鍵可以輸入搜索內容來全局搜索信息;在menuconfig中選項前面的括號裏,表示編入,空白表示去除,M表示模塊化( Legend: []built-in [ ] excluded module < > module capable );
注:[]表示不可以模塊化,<>表示可以模塊化。另外 linux內核中一個功能模塊有三種編譯方法:編入、去除和模塊化。所謂編入就是將這個模塊的代碼直接編譯連接到zImage中去;去除就是將這個模塊不編譯鏈接到zImage中;模塊化是將這個模塊仍然編譯,但是不會將其鏈接到zImage中,會將這個模塊單獨鏈接成一個內核模塊.ko文件,將來linux系統內核啓動起來後可以動態的加載或卸載這個模塊。

在這裏插入圖片描述
說到這裏就不得不提下menuconfig和Kconfig和.config和Makefile的關係:
1)menuconfig本身的軟件而並不負責提供內容菜單裏的內容(目錄結構,以及菜單項目的細節),它只負責提供menuconfig工作的這一套邏輯,譬如在通過上下左右箭頭按鍵來調整光標等。
2)菜單內容是由內核源碼樹各個目錄下的Kconfig文件來支持的,Kconfig文件中按照一定的格式包含了一個又一個的配置項,每一個配置項在make menuconfig中都會成爲一個菜單項目,也就是說menuconfig中顯示的菜單目錄結構和源碼目錄中的Kconfig的目錄結構是一樣的(例如,我們手動改一個Kconfig中的配置項,再次make menuconfig相應的在menuconfig中也會隨着改動)。即menuconfig的菜單內容來自於Kconfig文件,Kconfig文件是不變的,Kconfig文件只是決定有沒有這個菜單項,並不管這個菜單項的選擇結果
3)菜單項的配置選擇值在.config文件裏。譬如等於y的,等於m的… make menuconfig每次推出時會將我們更改過的配置重新寫入.config文件中記錄,下一次再次打開make menuconfig時會再次加載.config,最終去編譯內核時編譯連接程序會考慮.config中的配置值指導整個編譯連接過程。
4)Kconfig按照一定的格式來書寫,menuconfig程序可以識別這種格式,然後從中提取出有效信息組成menuconfig中的菜單項。將來在做驅動移植等工作時,有時需要自己添加Kconfig中的一個配置項來將某個設備驅動添加到內核的配置項目中,這時候就需要對Kconfig的配置項格式有所瞭解,否則就不會添加。 打開其中的一個Kconfig文件,例如drivers/net目錄下的Kconfig文件,例如其中的一段內容:
在這裏插入圖片描述

其中:
menuconfig:
表示菜單(本身屬於一個菜單中的項目,但是他又有子菜單項目),其後面的 NETDEVICES 的就是其中一個配置項的名字,這個名字前面添加CONFIG_後就構成了.config文件中的其中一個配置項CONFIG_NETDEVICES。一個menuconfig後面跟着的所有config項就是這個menuconfig的子菜單。這就是Kconfig中表示的目錄關係

depends:
配置項NETDEVICES依賴於另一個配置項NET。如果NET配置項爲Y或者M,則NETDEVICES配置項纔有意義;如果依賴的哪個配置項NET本身被設置爲N,則NETDEVICES配置項根本沒有意義。所以有時候你在menuconfig中如果找不到一個選項,但是這個選項在Kconfig中卻是有的,則可能的原因就是這個配置項依賴的一個配置項是不成立的。
另外 depends依賴的配置項可以是多個,而且還可以有邏輯運算。這種時候只要依賴項目運算式子的邏輯結果爲真則依賴就成立。
config:
表示菜單中的一個配置項(本身並沒有子菜單下的項目)。其後面IFB的就是其中一個配置項的配置項名字,這個字符串前面添加CONFIG_後就構成了.config中其中一個配置項名字CONFIG_IFB

tristate:
意思是三態,即3種狀態,t就是這個配置項可以被三種選擇,分別對應Y、N、M三種選擇方式,也就是menuconfig頁面中配置項前的<>的三種狀態

bool:
bool的意思是這個配置項只能被2種選擇,對應Y和N,即menuconfig頁面中[]的二種狀態

help:
幫助信息,告訴我們這個配置項的含義,以及如何去配置他,這裏的幫助信息和在menuconfig裏按問好?出現的幫助信息是的對應的。
在這裏插入圖片描述
source:
內核源碼目錄樹中每一個Kconfig都會source引入其所有子目錄下的Kconfig,從而保證了所有的Kconfig項目都被包含進menuconfig中。這個也告訴我們:如果你自己在linux內核中添加了一個文件夾,一定要在這個文件夾下創建一個Kconfig文件,然後在這個文件夾的上一層目錄的Kconfig中source引入這個文件夾下的Kconfig文件。

5)從上面可以知道:配置項被配置成Y、N、M會影響.config文件中的CONFIG_XXX變量的配置值。這個.config中的配置值(=y、=m、沒有)會影響最終的編譯鏈接過程。如果=y則會被編入(built-in),如果=m會被單獨連接成一個ko模塊,如果沒有則對應的代碼不會被編譯。那麼這麼是怎麼實現的?都是通過當前目錄下的makefile實現的。接着上述4)分析,打開drivers/net目錄下的makefile文件,舉其中一個例子:obj-$(CONFIG_IFB) += ifb.o
在這裏插入圖片描述
如果CONFIG_IFB變量值爲y,則obj += ifb.o,因此 ifb.c會被編譯;如果CONFIG_IFB變量未定義,則ifb.c不會被編譯。如果CONFIG_IFB變量的值爲m則會被連接成ko模塊(這個是在linux內核的Makefile中定義的規則)

把menuconfig中的菜單項、Kconfig中的配置項、.config中的一行、 Makefile中的一行,這4個東西結合起來理解,則整個linux內核的配置體系就明瞭了。

三、編譯
配置結束共,就執行make來完成編譯。注意:若莫名其妙的錯誤,可以試試先make distclean;另外編譯完成後得到的內核鏡像不在源碼樹的根目錄下,在arch/arm/boot這個目錄下。得到的鏡像名是zImage。

四、燒寫
這裏用tftp的方式燒寫內核,將鏡像文件zImage放到,放到tftp服務器共享目錄;打開開發板進入到Uboot界面(一定要將uboot的相關環境變量設置好,確保能和tftp服務器ping通);在uboot下用 tftp命令下載 如 tftp 0x30008000 zImage (0x30008000爲配置時的鏈接地址,zImage便是下載到該地址);下載完成就可以用bootm ox30008000來啓動內核了

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