隨着學習的深入,有必要了解下編譯的過程。尋找到一個出路。
前言
這篇文章知道C語言的“宏語句”的含義。
一、編譯過程簡單說說
從內核的編譯過程,我們知道:
1.首先要有一個.config文件(這個文件通過Make menuconfig產生)。
2.make命令根據.config和Makefile文件,最終生成vmlilnux這個內核文件。
3.vmlinux壓縮成zImage。
二、.config文件來龍去脈
在源碼的編寫時候,程序員需要寫一個叫Kconfig的文件。在整個kernel源碼中有很多的Kconfig文件並且他們是以“樹狀”的形式,層層聯繫起來(是聯繫,不是依賴)。
kbuild工具(源碼中的一個程序)會從某些指定的目錄(源碼的頂級目錄結構是規範好的)開始,搜索源碼中的所有Kconfig文件,然後配合Make menuconfig將內核可以配置的東西都呈現出來,用戶根據自己的需求,配置好內核。最終保存爲.config文件。
當然這裏提一點:整個內核很大,所有選項一項一項的配置完,然後再生成.config文件是非常難的事情。所以供應商一般都會給一個樣板.config文件,make menuconfig會自動加載相關配置。我們只需要做小修改就行。
三、.config文件
打開.config文件,會發現,裏面都是一些類似的“宏定義”內容。沒錯,它就類似一種開關的作用。告訴make我要什麼功能。記得編譯進去。
所以在看Makefile文件的時候,發現一些變量找不到的定義的,可以到.config文件裏面找找。
四、Kconfig文件
Kconfig位於kernel源碼內大部分的文件夾中,是一種特殊格式的文件,負責提供kernel各個功能的配置選項。
文件的組織方式如下所示,編譯的時候傳入arch參數,找到對應的kconfig。文件通過source的方式引入新的kconfig文件。通過解析後,就可以形成menuconfig的組織形式
比如進行驅動移植等工作時,有時需要自己添加Kconfig中的一個配置項,從而將某個設備驅動添加到內核的配置項目中。
需要注意的是,Kconfig僅僅負責提供配置選項本身,而不提供各選項的值,
下面我們將以Block devices爲例,剖開這層面紗。
在Device Drivers–》Block devices裏面。
同時代碼對應drivers–》block目錄下的Kconfig
1.看Kconfig的第5行,對應是menuconfig,也就是說這個Kconfig是以一個單獨的頁面單獨展開。而config則代表的是一個配置選項。
2.而被 if BLK_DEV和 endif # BLK_DEV括起來的這些配置選項,就是Block devices菜單內的子選項
3.3.souce有點include的意思,每一個Kconfig都會source引入其所有子目錄下的Kconfig,從而保證了所有的Kconfig項目都被包含進menuconfig中。這個也告訴我們:如果自己在linux內核中添加了一個文件夾,一定要在這個文件夾下創建一個Kconfig文件,然後在這個文件夾的上一層目錄的Kconfig中source引入這個文件夾下的Kconfig文件
4.menuconfig或者config後面空格隔開的類似於DM9000和NETDEVICES 的就是這個配置項的配置項名字。配置項名字會被很多文件所引用(有點像宏定義),比如前面添加CONFIG_後就構成了.config中的配置項名字
5.bool或tristate後面跟着的字符串就是這些配置項在menuconfig的顯示內容
6.bool表示該配置項只能配置Y和N,對應menuconfig中的[ ];而tristate表示該配置項可以被配置爲Y,N,M,對應menuconfig中的<>;如圖所示
7.depends 的含義是依賴的意思,就比如上面的配置項DM9000_16BIT,它依賴於配置項DM9000,如果配置項DM9000是N,那麼DM9000_16BIT無論配置爲任何值,都無效了;另外,依賴是層層遞進的,如果依賴的依賴無效,也會導致配置項無效。同時依賴無效的話還會導致make menuconfig中配置項的消失
8.depends並不要求依賴的配置項一定是一個,可以是多個,而且還可以有邏輯運算(比如上面的!UML)。這種時候只要依賴項目運算式子的裸機結果爲真則依賴就成立
五、實例1:
需要編譯這個ttyprink的功能,在drivers/char目錄中包含了TTY_PRINTK設備驅動的源代碼drivers/char/ttyprintk.c。而在該目錄的Kconfig文件中包含關於
TTY_PRINTK的配置項:
可以看到TTY_PRINTK依賴EXPERT和TTY兩個配置項,也就是說這兩個配置項沒有打開,TTY_PRINTK是看不到的。通過查找,還真的在Device Drivers->Character devices中找不到TTY_PRINTK這個項。通過查找源碼,找到EXPERT這個項對應的Kconfig文件在/init/Kconfig。默認是no的,看這個文件的頭部,知道其對應根目錄的General setup菜單。打開後找到
選擇上,然後再去看TTY_PRINTK就可以找到有了。
六、實例2:
假設想把自己寫的一個flash的驅動程序加載到工程中,而且能夠通過menuconfig配置內核時選擇該驅動該怎麼辦呢?
可以分三步:
第一:將你寫的hello.c 文件添加到/drivers/char/ hello目錄下。
第二:修改/drivers/char/ hello目錄下的kconfig文件:
config HELLO_MODULE
tristate "hello-tristate"
default y
help
this is help test
第三:修改該目錄下makefile文件。
添加如下內容:
obj-$(CONFIG_HELLO_MODULE) += hello.o
第四:修改上層目錄/drivers/char中Kconfig文件
這樣,當你運行make menucofnig時,你將發現 hello-tristate選項,如果你選擇了此項。
該選擇就會保存在.config文件中。體現爲
這將是在hello/Makefile中
obj-$(CONFIG_HELLO_MODULE) += hello.o
等價爲
obj-y += hello.o
系統在調用hello下的makefile 時,將會把 hello.o 加入到內核中。即可達到你的目的。
七、實例3
爲演示Kconfig不同的數據類型的效果,編寫如下例程:
Kconfig文件:
config HELLO_MODULE
tristate "hello-tristate"
default y
help
this is help test
config HELLO_MODULE2
bool "hello-bool"
default y
help
this is help test
config HELLO_MODULE3
string "helllo-string"
default "str-test"
config HELLO_MODULE4
hex "hello-hex"
config HELLO_MODULE5
int "hello-int"
最終生成的.config文件如下
可以看到,會自動在名字的前面加上CONFIG_這樣的關鍵字。