# Getting Strarted with the Kernel ![](https://i.imgur.com/1svjmpy.png) # user-space & kernel space ![](https://i.imgur.com/p8okHDW.png) process context > When an application executes a system call, we say that the kernel is executing on behalf of the application. Furthermore, the application is said to be executing a system call in kernel-space, and the kernel is running in **process context**.This relationship— that applications call into the kernel via the system call interface—is the fundamental manner in which applications get work done interrupt context > To provide synchronization, the kernel can disable interrupts—either all interrupts or just one specific interrupt number. In many operating systems, including Linux, the interrupt handlers do not run in a process context. Instead, they run in a special > **interrupt context** that is not associated with any process.This special context exists solely to let an interrupt handler quickly respond to an interrupt, and then exit. # **Kconfig文件的用途-決定kernel編譯環境** ![](https://i.imgur.com/Gujys6h.png) 配置選項是以樹的形式組織的,每個選項都有其自己的依賴關係。 這些依賴關係決定了選項是否是可見的。父選項可見,子選項才能可見。 核心原始碼的目錄下都有兩個文件 Kconfig(2.4版本是Config.in)和 Makefile。 分佈到各目錄的Kconfig構成了一個分散式的核心配置資料庫, 每個 Kconfig分別描述了與所屬目錄文件相關的核心配置功能表。 在核心配置 make menuconfig(或 xconfig 等)時, 從 Kconfig 中讀出功能表,用戶選擇後保存到 .config的核心配置文件中。 在核心編譯時,主Makefile 調用這個 .config,就知道了用戶的選擇。 *上面的內容說明了, Kconfig 就是對應著核心的配置功能表。 * **假如想添加新的驅動到核心的原始碼中,修改 Kconfig,這樣就能夠選擇這個驅動** * **假如想編譯這個驅動,要修改 Makefile,所以添加新的驅動時需要修改的文件有兩種(注意不只是兩個**) Kconfig Makefile 要想知道怎麼修改這兩種文件,就要知道兩種文件的語法結構,詳細可參考kernel root下面這份文件 > Documentation/kbuild/kconfig-language.txt Kconfig 每個功能表都有一個關鍵字標識,最常見的就是config ``` config MODVERSIONS bool "Set version information on all module symbols" depends MODULES help Usually, modules have to be recompiled whenever you switch to a new kernel. ... ``` 每行都是以關鍵字開始,並可以接多個參數。 "config" 為定義了一新的配置選項。 而緊接著的下面幾行定義了該配置選項的屬性。 屬性可以是該配置選項的類型,輸入提示(input prompt),依賴關係,幫助資訊和預設值。 配置選項可以用相同的名字定義多次,但每個定義只能有一個輸入提示並且類型不能衝突。 語法: config symbol是個新的標記的功能表項,options是在這個新的功能表項下的屬性和選項 其中options部分有: - 類型定義:"bool"/"tristate"/"string"/"hex"/"int" 每個config功能表項都要有類型定義,每個配置選項都必須指定類型。 有兩個基本類型:tristate 和 string,其他類型都是基於這兩個基本類型。 * bool布林類型、 * tristate三態:內建、模組、移除、 * string字串、 * hex十六進位、 * integer整型 例如config HELLO_MODULE bool "hello test module" bool 類型的只能選或不選,tristate 類型的選項多了編譯成核心模組的選項, 假如選擇編譯成核心模組,則會在 .config 中生成一個 CONFIG_HELLO_MODULE=m 的配置, 假如選擇內建,就是直接編譯進核心,就會在 .config 中生成一個 CONFIG_HELLO_MODULE=y 的配置. 類型定義可以用輸入提示,所以下面的兩個例子是等價的: bool "Networking support" and bool prompt "Networking support" - 依賴型定義 depends on或 requires 指此功能表的出現與否是依賴另一個定義 config HELLO_MODULE bool "hello test module" depends on ARCH_PXA 這個例子表明HELLO_MODULE這個功能表項只對XScale處理器有效。 - 輸入提示: "prompt" <prompt> ["if" <expr>] 每個功能表選項最多只能有一個顯示給用戶的輸入提示。 可以用 "if" 來表示該提示的依賴關係,當然這是可選的。 - 預設值:"default" <expr> ["if" <expr>] 一個配置選項可以有任意多個預設值。 如果有多個預設值,那麼只有第一個被定義的值是可用的。 預設值並不是只限于應用在定義他們的功能表選項。 這就意味著預設值可以定義在任何地方或被更早的定義覆蓋。 如果用戶沒有設置(通過上面的輸入提示),配置選項的值就是預設值。 如果可以顯示輸入提示的話,就會把預設值顯示給用戶,並可以讓用戶進行修改。 預設值的依賴關係可以用 "if" 添加。(可選項) - 依賴關係:"depends on"/"requires" <expr> 為一功能表選項定義依賴關係。 如果定義了多個依賴關係,它們之間用 '&&' 間隔。 依賴關係也可以應用到該功能表中所有的其他選項(同樣接受一if運算式), 所以下面的兩個例子是等價的: ``` bool "foo" if BAR default y if BAR and depends on BAR bool "foo" default y ``` - 反向依賴關係:"select" <symbol> ["if" <expr>] 儘管普通的依賴關係可以降低一選項的上限,反向依賴能將這一限制降的更低。 當前功能表選項的值是symbol的最小值。 如果symbol被選擇了多次,上限就是其中的最大值。 反向依賴只能用在 boolean 或 tristate 選項上。 - 資料範圍:"range" <symbol> <symbol> ["if" <expr>] 為int和hex類型的選項設置可以接受輸入值範圍。 用戶只能輸入大於等於第一個symbol,小於等於第二個symbol的值。 選單依賴關係 ------------ 依賴關係決定了功能表選項是否可見,也可以減少tristate的輸入範圍。 tristate邏輯比boolean邏輯在表達式中用更多的狀態(state)來表示模組的狀態。 依賴關係運算式的語法如下: <expr> ::= <symbol> (1) <symbol> '=' <symbol> (2) <symbol> '!=' <symbol> (3) '(' <expr> ')' (4) '!' <expr> (5) <expr> '&&' <expr> (6) <expr> '||' <expr> (7) 運算式是以優先順序的降冪列出的。 (1) 將symbol賦給運算式。boolean和tristate類型的symbol直接賦給運算式。 所有其他類型的symbol都賦 'n'。 (2) 如果兩個symbol相等,返回'y',否則為'n'。 (3) 如果兩個symbol相等,返回'n',否則為'y'。 (4) 返回運算式的值。用於改變優先順序。 (5) 返回 (2-/expr/) 的結果。 (6) 返回 min(/expr/,/expr/) 的結果。 (7) 返回 max(/expr/,/expr/) 的結果。 一個運算式的值可以是'n','m'或'y'(或者是計算的結果 0,1,2)。 當運算式的值為'm'或'y'的時候,選單選項才是可見的。 symbol有兩種類型:不可變的和可變的。不可變的symbol是最普通的, 由'config'語句定義,完全由數字、字母和下劃線組成(alphanumeric characters or underscores)。 不可變的symbol只是運算式的一部分。經常用單引號或雙引號括起來。 在引號中,可以使用任何字元,使用引號要用轉義字元'\'。 功能表結構 -------- 功能表在樹中的位置可由兩種方法決定。第一種可以是這樣: menu "Network device support" depends NET config NETDEVICES ... endmenu 所有的在"menu" ... "endmenu" 之間都是"Network device support"的子功能表。 所有的子功能表選項都繼承了父功能表的依賴關係, 比如,"NET"的依賴關係就被加到了配置選項NETDEVICES的依賴列表中。 還有就是通過分析依賴關係生成功能表的結構。 如果功能表選項在一定程度上依賴於前面的選項,它就能成為該選項的子功能表。 首先,前面的(父)選項必須是依賴列表中的一部分並且它們中必須有滿足下面兩個條件的選項: - 如果父選項為'n',子選項必須不可見。 - 如果父選項可見,子選項才能可見。 config MODULES bool "Enable loadable module support" config MODVERSIONS bool "Set version information on all module symbols" depends MODULES comment "module support disabled" depends !MODULES MODVERSIONS 直接依賴 MODULES,這就意味著如果MODULES不為'n',該選項才可見。 換句話說,當MODULES可見時,選項才可見(MODULES的(空)依賴關係也是選項依賴關係的一部分)。 Kconfig 語法 ------------ 配置檔描述了功能表選項,每行都是以一關鍵字開頭(除了幫助資訊)。 下面的關鍵字結束一功能表選項: - config - menuconfig - choice/endchoice - comment - menu/endmenu - if/endif - source 前5個同樣可以用在功能表選項定義的開始。 config: "config" <symbol> <config options> 定義了一配置選項 <symbol> 並且可以接受任何前面介紹的屬性。 menuconfig: "menuconfig" <symbol> <config options> 此關鍵字和前面的關鍵字很相似,但它在前面的基礎上要求所有的子選項作為獨立的行顯示。 ( This is similar to the simple config entry above, but it also gives a hint to front ends, that all suboptions should be displayed as a separate list of options.) choices: "choice" <choice options> <choice block> "endchoice" 該關鍵字定義了一組選擇項,並且選項可以是前面描述的任何屬性。 儘管boolean只允許選擇一個配置選項,tristate可以於多個配置選項設為'm', 但選項只能是boolean或tristate類型。 這可以在一個硬體有多個驅動的情況下使用,最終只有一個驅動被編譯進/載入到核心, 但所有的驅動都可以編譯成模組。 選項可以接受的另一個選項是"optional",這樣選項就被設置為'n',沒有被選中的。 comment: "comment" <prompt> <comment options> 這裏定義了在配置過程中顯示給用戶的注釋,該注釋還將寫進輸出檔中。 唯一可用的可選項是依賴關係。 menu: "menu" <prompt> <menu options> <menu block> "endmenu" 這裏定義了一個功能表,詳細資訊請看前面的"功能表結構"。 唯一可用的可選項是依賴關係。 if: "if" <expr> <if block> "endif" 這裏定義了if結構。依賴關係<expr>被加到所有在if ... endif 中的功能表選項中。 (lb:請看linux-source/drivers/ata/Kconfig:20) Makefile 在 linux2.6.x/Documentation/kbuild 目錄下有詳細關於 kernel makefile 的介紹。 核心的Makefile分為5個組成部分: * Makefile 最頂層的Makefile * .config 核心的當前配置文件,編譯時成為定層Makefile的一部分 * arch/$(ARCH)/Makefile 和體系結構相關的 Makefile * s/ Makefile.* 一些Makefile的通用規則 * kbuild Makefile 各級目錄下的大約有500個文件,編譯時根據上層 Makefile 傳下來的 * 巨集定義和其他編譯規則,將源代碼編譯成模組或編入核心 頂層的Makefile文件讀取 .config 文件的內容,並且在總體上負責建立核心和模組。 Arch Makefile 則提供補充系統結構相關的資訊。 s 目錄下的 Makefile 文件包含了任何根據 kbuild Makefile 構建核心所需的定義和規則。 (其中 .config 的內容是在 make menuconfig 的時候,通過 Kconfig 文件配置的結果。 舉個例子: 假設想把自己寫的一個flash的驅動程式載入到工程中,而且能夠通過 menuconfig 配置 核心時選擇該驅動該怎麼辦呢?能夠分三步: 第一:將您寫的 flashtest.c 文件添加到 /driver/mtd/maps/ 目錄下。 第二:修改 /driver/mtd/maps 目錄下的 kconfig 文件: config MTD_flashtest tristate “ap71 flash" 這樣當 make menuconfig 時 ,將會出現 ap71 flash選項。 第三:修改該目錄下makefile文件。 添加如下內容:obj-$(CONFIG_MTD_flashtest)+= flashtest.o 這樣,當您運行 make menucofnig 時,您將發現ap71 flash選項。 假如您選擇了此項,該選擇就會保存在 .config 文件中。 當您編譯核心時,將會讀取 .config 文件,當發現 ap71 flash 選項為 yes 時, 系統在呼叫 /driver/mtd/maps/ 下的 makefile 時,將會把 flashtest.o 加入到核心中。