前面我們介紹模塊編程的時候介紹了驅動進入內核有兩種方式:模塊和直接編譯進內核,並介紹了模塊的一種編譯方式——在一個獨立的文件夾通過makefile配合內核源碼路徑完成
那麼如何將驅動直接編譯進內核呢?
在我們實際內核的移植配置過程中經常聽說的內核裁剪又是怎麼麼回事呢?
我們在進行linux內核配置的時候經常會執行make menuconfig這個命令,然後屏幕上會出現以下界面:
這個界面是怎麼生成的呢?
跟我們經常說的內核配置與與編譯又有什麼關係呢?
下面我們藉此來講解一下linux內核的配置機制及其編譯過程。
一、配置系統的基本結構
Linux內核的配置系統由三個部分組成,分別是:
1、Makefile:分佈在 Linux 內核源代碼根目錄及各層目錄中,定義 Linux 內核的編譯規則;
2、配置文件(config.in(2.4內核,2.6內核)):給用戶提供配置選擇的功能;
3、配置工具:包括配置命令解釋器(對配置腳本中使用的配置命令進行解釋)和配置用戶界面(提供基於字符界面、基於 Ncurses 圖形界面以及基於 Xwindows 圖形界面的用戶配置界面,各自對應於 Make config、Make menuconfig 和 make xconfig)。
這些配置工具都是使用腳本語言,如 Tcl/TK、Perl 編寫的(也包含一些用 C 編寫的代碼)。本文並不是對配置系統本身進行分析,而是介紹如何使用配置系統。所以,除非是配置系統的維護者,一般的內核開發者無須瞭解它們的原理,只需要知道如何編寫 Makefile 和配置文件就可以。
二、makefile menuconfig過程講解
當我們在執行make menuconfig這個命令時,系統到底幫我們做了哪些工作呢?
這裏面一共涉及到了一下幾個文件我們來一一講解
Linux內核根目錄下的scripts文件夾
arch/$ARCH/Kconfig文件、各層目錄下的Kconfig文件
Linux內核根目錄下的makefile文件、各層目錄下的makefile文件
Linux內核根目錄下的的.config文件、arm/$ARCH/下的config文件
Linux內核根目錄下的 include/generated/autoconf.h文件
1)scripts文件夾存放的是跟make menuconfig配置界面的圖形繪製相關的文件,我們作爲使用者無需關心這個文件夾的內容
2)當我們執行make menuconfig命令出現上述藍色配置界面以前,系統幫我們做了以下工作:
首先系統會讀取arch/$ARCH/目錄下的Kconfig文件生成整個配置界面選項(Kconfig是整個linux配置機制的核心),那麼ARCH環境變量的值等於多少呢?
它是由linux內核根目錄下的makefile文件決定的,在makefile下有此環境變量的定義:
或者通過 make ARCH=arm menuconfig命令來生成配置界面,默認生成的界面是所有參數都是沒有值的
比如教務處進行考試,考試科數可能有外語、語文、數學等科,這裏相當於我們選擇了arm科可進行考試,系統就會讀取arm/arm/kconfig文件生成配置選項(選擇了arm科的卷子),系統還提供了x86科、milps科等10幾門功課的考試題
3)假設教務處比較“仁慈”,爲了怕某些同學做不錯試題,還給我們準備了一份參考答案(默認配置選項),存放在arch/$ARCH/configs下,對於arm科來說就是arch/arm/configs文件夾:
此文件夾中有許多選項,系統會讀取哪個呢?內核默認會讀取linux內核根目錄下.config文件作爲內核的默認選項(試題的參考答案),我們一般會根據開發板的類型從中選取一個與我們開發板最接近的系列到Linux內核根目錄下(選擇一個最接近的參考答案)
#cp arch/arm/configs/s3c2410_defconfig .config
4).config
假設教務處留了一個心眼,他提供的參考答案並不完全正確(.config文件與我們的板子並不是完全匹配),這時我們可以選擇直接修改.config文件然後執行make menuconfig命令讀取新的選項
但是一般我們不採取這個方案,我們選擇在配置界面��通過空格、esc、回車選擇某些選項選中或者不選中,最後保存退出的時候,Linux內核會把新的選項(正確的參考答案)更新到.config中,此時我們可以把.config重命名爲其它文件保存起來(當你執行make distclean時系統會把.config文件刪除),以後我們再配置內核時就不需要再去arch/arm/configs下考取相應的文件了,省去了重新配置的麻煩,直接將保存的.config文件複製爲.config即可.
5)經過以上兩步,我們可以正確的讀取、配置我們需要的界面了
那麼他們如何跟makefile文件建立編譯關係呢?
當你保存make menuconfig選項時,系統會除了會自動更新.config外,還會將所有的選項以宏的形式保存在
Linux內核根目錄下的 include/generated/autoconf.h文件下
內核中的源代碼就都會包含以上.h文件,跟宏的定義情況進行條件編譯。
當我們需要對一個文件整體選擇如是否編譯時,還需要修改對應的makefile文件,例如:
我們選擇是否要編譯s3c2410_ts.c這個文件時,makefile會根據CONFIG_TOUCHSCREEN_S3C2410來決定是編譯此文件,此宏是在Kconfig文件中定義,當我們配置完成後,會出現在.config及autconf中,至此,我們就完成了整個linux內核的編譯過程。
最後我們會發現,整個linux內核配置過程中,留給用戶的接口其實只有各層Kconfig、makefile文件以及對應的源文件。
比如我們如果想要給內核增加一個功能,並且通過make menuconfig控制其聲稱過程
首先需要做的工作是:修改對應目錄下的Kconfig文件,按照Kconfig語法增加對應的選項;
其次執行make menuconfig選擇編譯進內核或者不編譯進內核,或者編譯爲模塊,.config文件和autoconf.h文件會自動生成;
最後修改對應目錄下的makefile文件完成編譯選項的添加;
最後的最後執行make zImage命令進行編譯。
三、具體實例
下面我們以前面做過的模塊實驗爲例,講解如何通過make menuconfig機制將前面單獨編譯的模塊編譯進內核或編譯爲模塊
假設我已經有了這麼一個驅動:
modules.c
1.#include <linux/module.h> /*module_init()*/
2.#include <linux/kernel.h> /* printk() */
3.#include <linux/init.h> /* __init __exit */
4.
5.#define DEBUG //open debug message
6.
7.#ifdef DEBUG
8.#define PRINTK(fmt, arg...) printk(KERN_WARNING fmt, ##arg)
9.#else
10.#define PRINTK(fmt, arg...) printk(KERN_DEBUG fmt, ##arg)
11.#endif
12.
13./* Module Init & Exit function */
14.static int __init myModule_init(void)
15.{
16. /* Module init code */
17. PRINTK("myModule_init\n");
18. return 0;
19.}
20.
21.static void __exit myModule_exit(void)
22.{
23. /* Module exit code */
24. PRINTK("myModule_exit\n");
25. return;
26.}
27.
28.module_init(myModule_init);
29.module_exit(myModule_exit);
30.
31.MODULE_AUTHOR("dengwei"); /*模塊作者,可選*/
32.MODULE_LICENSE("GPL"); /*模塊許可證明,描述內核模塊的許可權限,必須*/
33.MODULE_DESCRIPTION("A simple Hello World Module"); /*模塊說明,可選*/
Step1:將modules.c拷到drivers/char/目錄下(這個文件夾一般存放常見的字符驅動)
Step2: vi driver/char/Kconfig,在
config DEVKMEM後添加以下信息
config MODULES
tristate "modules device support"
default y
help
Say Y here,the modules will be build in kernel.
Say M here,the modules willbe build to modules.
Say N here,there will be nothing to be do.
Step3:make menuconfig
Device driver-character devices
[*]modules device suppor
Step4:vi driver/char/Makefile,在js-rtc後添加
obj-$(CONFIG_MODULES)+= modules.o
CONFIG_MODULES 必須跟上面的Kconfig中保持一致,系統會自動添加CONFIG_前綴
modules.o必須跟你加入的.c文件名一致
最後執行:make zImage modules就會被編譯進內核中
第三步:
Step3:make menuconfig
Device driver-character devices
[M]modules device suppor
把星號在配置界面通過空格改爲M,最後執行make modules,在driver/char/目錄下會生成一個modules.ko文件
跟我們前面講的單獨編譯模塊效果一樣,也會生成一個模塊,將它考入開發板執行insmod moudles.ko,即可將生成的模塊插入內核使用。
PS:自己的看法
Linux內核的make menuconfig實際上是執行了:
scripts/kconfig/mconf arch/mips/Kconfig
mconf表示是menuconfig,如果是用基於QT的配置工具,則執行的將會是qconf,arch/mips/Kconfig是要讀取的Kconfig文件,這個會因平臺而異,這裏因爲針對的是MIPS平臺,故讀取的是arch/mips/目錄下的Kconfig文件。
如果Linux源碼樹頂層目錄下已有.config文件,make menuconfig則從.config文件取默認參數,如果沒有.config則從各個Kconfig中取默認參數。
mconf會把用戶的選擇保存到Linux源碼樹頂層目錄的.config文件中,然後解析該文件並將解析結果寫入到include/linux/autoconf.h中。include/linux/autoconf.h將會被include/linux/config.h包含,因此,需要關心配置情況的內核源文件只需要#include <linux/config.h>即可。
mconf解析.config文件時所採用的規則具體要仔細分析mconf.c源代碼。