1. 程式人生 > >2、內核的配置和移植

2、內核的配置和移植

解決方案 有意義 crypt find 大寫字母 req 含義 如何 tools

1.linux內核源碼目錄結構1

源碼從哪裏來
  • 之前講過,我們使用2.6.35.7版本的內核。這個版本的內核有三種:第一種是kernel.org上的官方版本,第二種是三星移植過的,第三種是九鼎X210的移植版本。我們講課時使用第三種內核來講解,後面的移植實驗使用第二種內核來移植。
  • 源碼在開發板光盤中有。可以自己去linux下解壓然後make distclean清理然後再次打包傳輸到windows下去解壓分析;也可以直接去我網盤中下載我打包好的。
  • 解壓後最終在windows下得到了一個kernel的源碼目錄樹,這個源碼目錄就是九鼎以三星移植過的內核為原材料自己針對X210移植後的內核版本。
分析源碼目錄下的單個文件
1 .mailmap 開發者的郵箱
2 COPYING 版權
3 COPYING.txt
4 CREDITS 感謝
5 initrd.img.cpio 設備樹傳參
6 Kbuild 就是內核編譯的意思。這個文件就是linux內核特有的內核編譯體系需要用到的文件。
7 Makefile 這個是linux內核的總makefile,整個內核工程用這個Makefile來管理的。
8 mk 是九鼎在移植時自己添加的,不是linux內核本身的東西。九鼎添加這個文件的作用是用這個文件來整天管理kernel目錄的配置和編譯,也就是說這個文件有點類似於我們之前移植uboot時自己創建的那個cp.sh。
9 README 說明
簡單講一下linux內核的配置體系。
  • linux內核很龐大,裏面模塊很多,而且可配置性非常高。所以linux源代碼的配置是一個很復雜的事情,必須要有一套很復雜的機制來保證linux內核可以被正確的配置。(對比一下uboot,uboot的配置項都是在xxx.h中,用宏定義來表示的。uboot的這種方式很依賴於人的水平,因為uboot的配置體系很簡單。)
  • linux內核本身配置項有上千個,光靠人眼睛去看腦袋去記根本不可能,所以內核發明了一種體系用來幫助人進行簡單化的配置。這種體系就是我們本次重點要研究的東西。
  • Kbuild、Kconfig等文件,都是和內核的配置體系有關的

2.linux內核源碼目錄結構2

1 arch arch是architecture的縮寫,意思是架構。arch目錄下是好多個不同架構的CPU的子目錄,譬如arm這種cpu的所有文件都在arch/arm目錄下,X86的CPU的所有文件都在arch/x86目錄下。
2 block 在linux中block表示塊設備(以塊(多個字節組成的整體,類似於扇區)為單位來整體訪問),譬如說SD卡、iNand、Nand、硬盤等都是塊設備。你幾乎可以認為塊設備就是存儲設備。block目錄下放的是一些linux存儲體系中關於塊設備管理的代碼。
3 crypto 英文意思是加密。這個目錄下放了一些各種常見的加密算法的C語言代碼實現。譬如crc32、md5、sha1等。
4 Documentation 裏面放了一些文檔。
5 drivers 驅動目錄,裏面分門別類的列出了linux內核支持的所有硬件設備的驅動源代碼。
6 firmware 固件。什麽是固件?固件其實是軟件,不過這個軟件是固化到IC裏面運行的叫固件。就像S5PV210裏的iROM代碼。
7 fs fs就是file system,文件系統,裏面列出了linux支持的各種文件系統的實現。
8 include 頭文件目錄,公共的(各種CPU架構共用的)頭文件都在這裏。每種CPU架構特有的一些頭文件在arch/arm/include目錄及其子目錄下
9 init init是初始化的意思,這個目錄下的代碼就是linux內核啟動時初始化內核的代碼。
10 ipc ipc就是inter process commuication,進程間通信,裏面都是linux支持的IPC的代碼實現。
11 kernel kernel就是內核,就是linux內核,所以這個文件夾下放的就是內核本身需要的一些代碼文件。
12 lib lib是庫的意思,這裏面都是一些公用的有用的庫函數,註意這裏的庫函數和C語言的庫函數不一樣的。在內核編程中是不能用C語言標準庫函數,這裏的lib目錄下的庫函數就是用來替代那些標準庫函數的。譬如在內核中要把字符串轉成數字用atoi,但是內核編程中只能用lib目錄下的atoi函數,不能用標準C語言庫中的atoi。譬如在內核中要打印信息時不能用printf,而要用printk,這個printk就是我們這個lib目錄下的。
13 mm mm是memory management,內存管理,linux的內存管理代碼都在這裏。
14 net 該目錄下是網絡相關的代碼,譬如TCP/IP協議棧等都在這裏。
15 samples 一些實例代碼
16 scripts 腳本,這個目錄下全部是腳本文件,這些腳本文件不是linux內核工作時使用的,而是用來輔助對linux內核進行配置編譯生產的。我們並不會詳細進入分析這個目錄下的腳本,而是通過外圍來重點學會配置和編譯linux內核即可。
17 security 安全相關的代碼。不用去管。
18 sound 音頻處理相關的。
19 tools linux中用到的一些有用工具
20 usr 目錄下是initramfs相關的,和linux內核的啟動有關,暫時不用去管。
21 virt 內核虛擬機相關的,暫時不用管。
  • 總結:這麽多目錄跟我們關系很緊密的就是arch和drivers目錄,然後其他有點相關的還有include、block、mm、net、lib等目錄。

3.內核配置和編譯體驗

先確認Makefile
  • 主要是檢查交叉編譯工具鏈有沒有設置對。CROSS_COMPILE ?= /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
  • 確認ARCH = arm。主要目的是為了編譯時能找到arch/arm目錄。
技術分享圖片 make x210ii_qt_defconfig
  • 最後只要出現:configuration written to .config這句話,就證明我們的操作是正確的。如果沒有出現這句話,就有錯誤。
  • 可能出現的錯誤1:名字敲錯了。名字是字符串匹配的,一定要正確。
  • 註意:如果這一步配置沒有得到.config文件,是不能進行到下一步的。實際測試時沒有.config也可以make menuconfig,但是這樣做出來的內核編譯和燒寫運行應該是有問題的。
技術分享圖片 make menuconfig 技術分享圖片 技術分享圖片
  • 可能出現的錯誤1:ncurses庫沒裝
  • 錯誤信息:
*** Unable to find the ncurses libraries or the
*** required header files.
*** make menuconfig requires the ncurses libraries.
***
*** Install ncurses (ncurses-devel) and try again.
  • 解決方案: apt-get install libncurses5-dev (參考了:http://blog.csdn.net/yao_qinwei/article/details/8805101)
  • 可能出現的錯誤2:屏幕太小
  • 錯誤信息:
Your display is too small to run Menuconfig!
It must be at least 19 lines by 80 columns.
  • 解決方案:全屏,或者是把字體調小。
  • 總結:make menuconfig是第二步配置,具體的用法和配置意義在後面課程講。我們這裏因為是九鼎已經移植過的,所以第二步配置是可以不做的,直接退出即可。
  • 用鍵盤的向右方向鍵移動到EXIT,按回車退出。

make

  • 可能出現的錯誤1:莫名其妙的錯誤,可以試試先make distclean
  • 代碼本身的錯誤:具體問題具體分析
  • 編譯完成後得到的內核鏡像不在源碼樹的根目錄下,在arch/arm/boot這個目錄下。得到的鏡像名是zImage

4.內核的配置原理1

燒寫測試 配置的關鍵是得到.config文件
  • .config以.開頭,是一個隱藏文件,因此平時是看不到的,需要ls -a來看
  • 當我們make distclean後(也就是說默認情況下)是沒有.config文件的,我們配置的兩步過程就是為了得到內容合適的.config文件
  • .config文件是linux內核在編譯過程中很重要的一個文件,其作用類似與uboot中的include/configs/x210_sd.h,內核在編譯過程中會讀取.config中的配置項,並且用這些配置項去指導整個編譯鏈接過程。
  • .config文件的格式類似於腳本文件,其中內容為類似於於:CONFIG_ARM=y的一個一個的配置項。這些配置項就類似於腳本文件中定義的一個一個變量,所以這一行可以被理解為定義了一個變量CONFIG_ARM,這個變量的值為y。
  • .config文件中每一行都是一個配置項,從.config文件的規模可以看出linux內核的可配置項有兩三千個。所以linux內核是高度可配置的,而且linux內核的所有配置項很難全部搞明白。因為linux內核的配置項太多太繁雜超出了人的大腦能夠記憶和處理的數量級,因此linux內核不像uboot那樣直接手工配置,而是發明了一個圖形化的配置工具menuconfig。
make xx_defconfig make menuconfig相配合
  • 我們為了對.config文件中的兩三千個配置項做逐一合適的配置,專門發明了兩步結合的配置方式。
  • 其實只要人的記憶足夠好,大腦足夠厲害,完全可以手工去書寫/修改.config文件完成內核配置,最終只要.config中內容是正確的,就不影響編譯過程。
  • 第一步:make xxx_defconfig解決的問題是大部分的配置項(這一步結束後99%的配置項就已經正確了),下來就是對個別不同的針對我們的開發板進行細節調整,細節調整就通過make menuconfig來完成。
  • make xxx_defconfig這一步其實是參考別人已經做好的,這樣做有很多好處:減少很多工作量,避開了很多自己不懂的配置項(譬如對內存管理的、調度系統的等模塊的配置項),我們只用管自己需要管的。
  • make menuconfig其實就是讀取第一步得到的 .config,然後給我們一個圖形化的界面,讓我們可以更加容易的找到自己想要修改的配置項,然後更改配置他。
make xx_defconfig到底做了什麽?
  • make x210ii_qt_defconfig 其實相當於:cp arch/arm/configs/x210ii_qt_defconfig .config
  • arch/arm/configs目錄下的這麽多個xxx_defconfig哪裏來的?其實這些文件都是別人手工配置好適合一定的開發板的.config文件後自己把.config文件保存過去的。譬如說我們用S5PV210這個SoC,針對這個SoC的開發板的最初配置肯定是三星的工程師去做的。

5.menuconfig的使用和演示

使用說明解釋
  • make ,menuconfig中本身自帶的提示就有所有的用法,這裏只要全部理解就可以了。
  • menuconfig中間的選擇區中有很多個選擇項,menuconfig中每個選擇項對應.config文件中的一個配置項,每一個選擇項都可以被選擇和配置操作,選擇區中的每一項都是有子目錄的,將光標放在選擇項上按Enter鍵可以進入子目錄(子目錄可能還會有子目錄)。選擇區太短放不下所有的一個目錄層級的選項,可以用箭頭按鍵的向上箭頭和向下箭頭來上翻和下翻。
  • 註:在menuconfig中操作相關的幾個鍵盤按鍵,主要是;Enter、ESC、四個方向箭頭按鍵。還有一些特殊字符按鍵,如/ ?
  • 向上和向下箭頭,主要用來在選擇項菜單中目錄瀏覽時上下翻
  • 回車,主要作用是選中並且執行select/exit/help。
  • ESC,主要作用是返回上一層
  • 向左和向右箭頭,主要作用是在菜單選項(select、exit、help)間切換。
  • 用法翻譯:
  • 箭頭按鍵導航整個菜單,回車按鍵選擇子菜單(註意選項後面有 --->的選項才是有子菜單的,沒有這個標識的沒有子菜單),高亮的字母是熱鍵(快捷鍵),鍵盤按鍵Y、N、M三個按鍵的作用分別是將選中模塊編入、去除、模塊化。雙擊ESC表示退出,按下?按鍵可以顯示幫助信息,按下/按鍵可以輸入搜索內容來全局搜索信息(類似於vi中的搜索),[]不可以模塊化,<>的才可以模塊化。

  • 註:linux內核中一個功能模塊有三種編譯方法:編入、去除、模塊化。
  • 編入就是將這個模塊的代碼直接編譯連接到zImage中去,* 號表示,快捷鍵:Y
  • 去除就是將這個模塊不編譯鏈接到zImage中, 空白 表示, 快捷鍵:N
  • 模塊化是將這個模塊仍然編譯,但是不會將其鏈接到zImage中,M 表示,快捷鍵:M
  • 模塊化會將這個模塊單獨鏈接成一個內核模塊.ko文件,將來linux系統內核啟動起來後可以動態的加載或卸載這個模塊。
  • 在menuconfig中選項前面的括號裏,*表示編入,空白表示去除,M表示模塊化, < > 表示可模塊化,[ ] 表示不可模塊化。

6.menuconfig的工作原理

menuconfig本身由一套軟件支持的
  • linux為了實現圖形化界面的配置,專門提供了一套配置工具menuconfig。
  • ncurses庫是linux中用來實現文字式的圖形界面,linux內核中使用了ncurses庫來提供 menuconfig
  • scripts\kconfig\lxdialog目錄下的一些c文件就是用來提供menuconfig的那些程序源代碼。
menuconfig讀取Kconfig文件
  • menuconfig本身的軟件只負責提供menuconfig工作的這一套邏輯(譬如在menuconfig中通過上下左右箭頭按鍵來調整光標,Enter ESC鍵等按鍵按下的響應),而並不負責提供內容(菜單裏的項目)。
  • menuconfig顯示的菜單內容(一方面是菜單的目錄結構,另一方面是每一個菜單項目的細節)是由內核源碼樹各個目錄下的 Kconfig 文件來支持的。Kconfig文件中按照一定的格式包含了一個又一個的配置項,每一個配置項在make menuconfig中都會成為一個菜單項目。而且menuconfig中顯示的菜單目錄結構和源碼目錄中的Kconfig的目錄結構是一樣的。
  • 在相應的Kconfig文件中刪除一個config項,則再次make menuconfig時這個項目已經看不到了。
menuconfig讀取/寫入.config文件
  • 剛才已經知道menuconfig的菜單內容來自於Kconfig文件,但是每一個菜單的選擇結果(Y、N、M)卻不是保存在Kconfig文件中的。Kconfig文件是不變的,Kconfig文件只是決定有沒有這個菜單項,並不管這個菜單項的選擇結果。
  • menuconfig工作時在我們make menuconfig打開時,他會讀取.config文件,並且用.config文件中的配置選擇結果來初始化menuconfig中各個菜單項的選擇值。
  • 總結:菜單項的項目內容從 Kconfig 文件來,菜單項的選擇值從 .config 文件來
  • 當我們每次退出make menuconfig時,menuconfig機制會首先檢查我們有沒有更改某些配置項的值,如果我們本次沒有更改過任意一個配置項目的值那直接退出;如果我們有改動配置項的值則會提示我們是否保存。此時如果點保存,則會將我們更改過的配置重新寫入.config文件中記錄,下一次再次打開make menuconfig時會再次加載.config,最終去編譯內核時編譯連接程序會考慮.config中的配置值指導整個編譯連接過程。
  • 總結:本次主要內容就是講:menuconfig和Kconfig和.config的關系。

7.Kconfig文件詳解1

Kconfig的格式
  • Kconfig按照一定的格式來書寫,menuconfig程序可以識別這種格式,然後從中提取出有效信息組成menuconfig中的菜單項。
  • 將來在做驅動移植等工作時,有時需要自己添加Kconfig中的一個配置項來將某個設備驅動添加到內核的配置項目中,這時候就需要對Kconfig的配置項格式有所了解,否則就不會添加。
  • #開頭的行是註釋行
  • menuconfig表示菜單(本身屬於一個菜單中的項目,但是他又有子菜單項目)、.config表示菜單中的一個配置項(本身並沒有子菜單下的項目)。技術分享圖片

技術分享圖片

技術分享圖片

  • menuconfig或者config後面空格隔開的大寫字母表示的類似於 NETDEVICES 的就是這個配置項的配置項名字,這個字符串前面添加CONFIG_後就構成了.config中的配置項名字。
  • 一個menuconfig後面跟著的所有config項就是這個menuconfig的子菜單。這就是Kconfig中表示的目錄關系。
  • 內核源碼目錄樹中每一個Kconfig都會source引入其所有子目錄下的Kconfig,從而保證了所有的Kconfig項目都被包含進menuconfig中。這個也告訴我們:如果你自己在linux內核中添加了一個文件夾,一定要在這個文件夾下創建一個Kconfig文件,然後在這個文件夾的上一層目錄的Kconfig中source引入這個文件夾下的Kconfig文件。
技術分享圖片 技術分享圖片

tristate和bool的含義
  • tristate 意思是三態 < >(3種狀態,對應Y、N、M三種選擇方式),bool 是要麽真要麽假 [ ](對應Y和N)。所以tristate的意思就是這個配置項可以被三種選擇,bool的意思是這個配置項只能被2種選擇。
技術分享圖片 技術分享圖片 技術分享圖片

技術分享圖片

8.Kconfig文件詳解2

depends的含義
  • depends中文意思是“取決於”或者“依賴於”,所以depends在這裏的意思是:本配置項依賴於另一個配置項。依賴的配置項為Y或者M,則本配置項才有意義;如果依賴的哪個配置項本身被設置為N,則本配置項根本沒有意義。
  • depends項目會導致make menuconfig的時候找不到一些配置項。所以你在menuconfig中如果找不到一個選項,但是這個選項在Kconfig中卻是有的,則可能的原因就是這個配置項依賴的一個配置項是不成立的。
  • depends並不要求依賴的配置項一定是一個,可以是多個,而且還可以有邏輯運算。這種時候只要依賴項目運算式子的裸機結果為真則依賴就成立。
技術分享圖片 技術分享圖片

help
  • 幫助信息,告訴我們這個配置項的含義,以及如何去配置他。
技術分享圖片 技術分享圖片

技術分享圖片

9.Kconfig和.config文件和Makefile三者的關聯

  • 配置項XXX被配置成Y、N、M會影響.config文件中的CONFIG_XXX變量的配置值
  • 這個.config中的配置值(=y、=m、沒有)會影響最終的編譯鏈接過程。如果=y則會被編入(built-in),如果=m會被單獨連接成一個ko模塊,如果沒有則對應的代碼不會被編譯。那麽這麽是怎麽實現的?都是通過makefile實現的。
  • obj-$(CONFIG_DM9000) += dm9000.o
  • 如果CONFIG_DM9000變量值為y,則obj += dm9000.o,因此dm9000.c會被編譯;如果CONFIG_DM9000變量未定義,則dm9000.c不會被編譯。如果CONFIG_DM9000變量的值為m則會被連接成ko模塊(這個是在linux內核的Makefile中定義的規則)
技術分享圖片 技術分享圖片

  • 總結:把menuconfig中的菜單項、Kconfig中的配置項、.config中的一行、 Makefile中的一行,這4個東西結合起來理解,則整個linux內核的配置體系就明了了。
  • menuconfig中的菜單項取決於Kconfig中配置項,我們在配置Kconfig後,會更改.config 中變量的值,在編譯的時候,Makefile會根據變量的值來決定哪些文件被編譯。

10.menuconfig的實驗學習思路

驗證menuconfig和.config的關系
  • make menuconfig時,會讀取.config中的配置值來初始化menuconfig中的配置項。
  • 驗證:如果理論正確的,那麽我自己手工修改了.config的配置後,再次make menuconfig時看到的初始值就應該是我手工修改的。
  • menuconfig中修改了(按Y、N、M)配置項的值,然後退出時保存,則這個保存結果會修改.config文件中的相應行。
  • 驗證:如果結論是正確的,那麽在menucofig中修改了配置後保存退出,再次去手工打開.config文件則可以看到相應配置的一行內容被修改了。
驗證menuconfig和Kconfig的關系
  • menuconfig讀取Kconfig的內容作為菜單項目內容。
  • 驗證1:在Kconfig中刪除一個config項,則再次make menuconfig時就看不到這個項目了。(上課時已經驗證過了)
  • 驗證2:在Kconfig中自己添加創建一個config項,則再次make menuconfig時就能看到多了一個項目。
驗證驗證menuconfig和Makefile的關系
  • 我找一個模塊,把他配制成y,然後去make編譯連接,最後得到的zImage中這個模塊就應該被編譯連接進去到zImage中了。
  • 驗證:
  • 方法一:去這個模塊對應的源代碼目錄看一下這個源碼有沒有被編譯
  • 方法二:去zImage對應的elf格式的vmlinux中查看符號
  • 方法三:將vmlinux反編譯(objdump)後得到的文件中找模塊對應的符號
  • 方法四:將zImage下載到開發板中啟動,啟動後看你的模塊能不能工作

2、內核的配置和移植