Linux-內核-學習筆記(11):內核配置和編譯原理

Linux-內核-學習筆記(11):內核配置和編譯原理

一、內核簡介

1. 操作系統

1.1、什麼是操作系統?

操作系統本質上是一個程序,由很多個源文件構成,需要編譯連接成操作系統程序。它主要作用就是管理計算機硬件,給應用程序提供一個運行環境。例如linux、windows、android、ucos就是操作系統。

1.2、操作系統核心功能

操作系統就相當於你的一個管家,是一些功能的綜合體,他會管理下面這些內容,幫助用戶解決一些複雜的分配和調用問題。

  • 內存管理:如果沒有操作系統,內存是需要程序自己來管理的。譬如在uboot中要使用內存時是自己隨便用的,自己定義內存的位置和大小,沒有註冊也沒有限制。這時候如果程序自己不小心把同一塊內存重複用了就會出現程序邏輯錯誤(覆蓋)。隨着系統變大了之後(內存多了),內存管理會非常麻煩。但是有了操作系統之後,操作系統負責管控所有的內存,所有的應用程序需要使用內存時都要向操作系統去申請和註冊,由操作系統的內存管理模塊來分配內存給你使用,這樣好處是可以保證內存使用不會衝突。
  • 進程調度:操作系統下支持多個應用程序同時運行(所以可以一邊聊QQ一邊看電影···),這是宏觀上的並行。實際上在單核心CPU上微觀上是不能並行的,宏觀上的並行就是操作系統提供的分時複用機制,也就是某個時間切換到一個進程下執行,執行完成後再切換到另外一個進程。操作系統的進程調度模塊負責在各個進程之間進行切換
  • 硬件設備管理:沒有操作系統時要控制任何硬件都要自己寫代碼,有了操作系統後操作系統本身會去控制各個硬件,應用程序就不用考慮硬件的具體細節了。操作系統的硬件設備管理模塊就是驅動模塊
  • 文件系統:文件系統是管理存儲設備的一種方式。存儲設備是由很多個扇區組成的,每個扇區有512/1024/2048/4096(各種)字節,存儲設備要以扇區爲單位進行讀寫。如果沒有文件系統,程序要自己去讀寫扇區,就得記得哪個文件在哪個扇區。有了文件系統之後用戶不用再關注扇區,只用關注文件系統中的目錄和文件名,而不用管這個文件在物理磁盤的哪個扇區。

同時,操作系統還有一些擴展功能:(1)協議棧。(2)有用的應用程序包。應用程序本身不屬於操作系統內核的一部分,應用程序是給人用的,面向某種功能的。譬如ping程序用來測試網絡是否聯通,ifconfig程序用來配置網卡。

1.3、內核和發行版區別

區別1:
內核是操作系統內核的簡稱內核負責實現操作系統的核心功能(資源管理模塊,譬如內存管理、調度系統······),內核不包括應用程序。所以說只有內核用戶是沒法用的(就像只有windows系統一樣),因爲人做任何事情都是通過相應的應用程序來完成的(需要給windows裝軟件)。所以賣操作系統的人把內核和一些常用的應用程序打包在一起提供給普通用戶,這就是操作系統的發行版(也就是普通意義上的操作系統)。所以 發行版包含內核和應用程序
區別2:
內核只有一個,只是版本不同。下載linux內核鏈接
發行版有很多。譬如ubuntu、redhat、suse、centos······都是使用一個內核做出來的,只是應用程序不同。

二、內核的框架

在這裏插入圖片描述
在瞭解內核時,首先要知道上述這種分層結構:應用層、操作系統層和硬件層。三者之間由於任務不同,主要操作的對象不同,實現了各層的着重點不同,但是三者之間又緊密聯繫着。層次之間實現下層被上層所調用,即硬件被OS所調用,而OS是給APP用來使用的。
操作系統管理着硬件層,它將硬件抽象成一個個的API,應用層在想要控制某個硬件設備時,通過操作系統層的API對硬件設備進行調用和控制,從而完成三個層次之間的協調配合。

1. 內核和驅動的關聯

(1)驅動其實屬於內核的一部分。驅動就是內核中的硬件設備管理模塊
(2)在內核態運行是管理員權限,而在用戶態則是用戶權限,是有一部分限制的。驅動工作在內核態。這裏將工作狀態劃分的目的主要是爲了在內核態時運行一些重要的程序,使其不受權限的束縛。所以驅動程序故障可能導致整個內核崩潰,驅動程序漏洞會使內核不安全。

2. 內核和應用程序的關聯

(1)應用程序不屬於內核,而是在內核之上的。
(2)應用程序工作在用戶態,是受限制的。每一個應用程序就是一個進程,系統在工作時有許多個應用程序和一個內核,但是同一時間CPU只能服務一個。應用程序如果想得到內存需要向CPU去申請(malloc和free),內核的目的是服務應用程序,所以應用程序纔是最終要實現的目標(重點是要生成能工作的APP),而操作系統只是一個手段(windows系統只是用來工作的)。
(3)應用程序故障不會導致內核崩潰,並且不會影響到其他的進程。因爲它們是相互獨立的進程,你的區域壞了不會影響我的區域。
(4)應用程序通過內核定義的API接口來調用內核工作。應用層執行應用需要調用硬件,所以需要通過內核來調用驅動從而操作硬件執行相應的動作,也可以理解爲內核就是爲應用程序提供底層資源管理的服務員

3. 內核和根文件系統的關聯

(1)根文件系統提供根目錄。整個文件系統是一個樹形的。從根目錄出發的方式就是絕對路徑,相對路徑的原理也是通過轉成絕對路徑去找的。反斜槓“/”就是根目錄,也就是最起始的目錄。我們常說的掛載mount就是一個連接點,如果說將XX掛載到XX,就是將這個東西的位置指定到某個特定的路徑下。
(2)進程1存放在根文件系統中,是用戶態和內核態的一個交界處。是整個系統中的第一個應用程序。
(2)內核啓動最後會去裝載根文件系統。剛開始內核啓動時沒有目錄的,整個操作系統的根目錄就是從根文件系統中來的。因此根文件系統爲操作系統啓動提供了很多必備的資源:根目錄和進程1

4. linux內核的模塊化設計

因爲linux內核很龐大,代碼量很大、東西很多,如果設計時完全設計成一體(各個文件、各個函數之間緊耦合),複雜度超出了人所能理解的範圍。所以模塊化設計也是一種必要。模塊化設計就是內核中各個功能模塊在代碼上是彼此獨立的,譬如說調度系統和內存管理系統之間並沒有全局變量的互相引用,甚至函數互相調用也很少,就算有也是遵循一個接口規範的。模塊化設計的目的就是實現功能模塊的松耦合

配置時可裁剪。linux內核在編譯之前可以進行配置,配置時可以選擇將組成內核的成千上萬個模塊每一個要或者不要。要了之後還有更多的一些細節的配置。
模塊化編譯和安裝。爲了操作方便,逐漸從靜態的升級變成了動態的升級(不需要重啓系統,更不需要重新燒錄系統)。這種動態的升級也是由模塊化來支持的。
源碼中使用條件編譯。這種在uboot中已經見過了。通過宏開關來控制編譯時候哪個編譯哪個不編譯,從而影響究竟使用了哪個模塊。

這種模塊化設計的優點是:(1)功能可裁剪、靈活性;(2)可擴展性(動態安裝卸載、新硬件支持);(3)利於協作。

三、內核配置和編譯原理

1. 內核源碼目錄分析

在分析內核源碼目錄之前,首先要將內核目錄解壓開,並將kernel目錄打包一份發送到windows端方便查看:
在這裏插入圖片描述
接近着分析kernel內核源碼目錄樹的各個目錄代表的意思:
在這裏插入圖片描述
(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)scripts:腳本,這個目錄下全部是腳本文件,這些腳本文件不是linux內核工作時使用的,而是用來輔助對linux內核進行配置編譯生產的。
(16)security:安全相關的代碼。不用去管。
(17)sound:音頻處理相關的。
(18)tools:linux中用到的一些有用工具。
(19)usr:目錄下是initramfs相關的,和linux內核的啓動有關,暫時不用去管。
(20)virt:內核虛擬機相關的,暫時不用管。
(21)Kbuild:Kbuild是kernel build的意思,就是內核編譯的意思。這個文件就是linux內核特有的內核編譯體系需要用到的文件。
(22)Makefile:這個是linux內核的總makefile,整個內核工程用這個Makefile來管理的。
(23)mk:是九鼎在移植時自己添加的,不是linux內核本身的東西。九鼎添加這個文件的作用是用這個文件來整天管理kernel目錄的配置和編譯,也就是說這個文件有點類似於我們之前移植uboot時自己創建的那個cp.sh。

2. 內核配置第一步(make x210ii_qt_defconfig)

2.1、方法演示

在進行make之前,先要檢查Makefile中的交叉編譯工具是否正確,並確定ARCH=arm以保證編譯時能找到arch/arm目錄。
在這裏插入圖片描述
在這裏插入圖片描述

2.2、原理分析

配置第一步的主要目的是爲了得到 .config文件。這個文件是一個隱藏文件,是linux內核在編譯過程中很重要的一個文件,其作用類似與uboot中的include/configs/x210_sd.h,內核在編譯過程中會讀取.config中的配置項,並且用這些配置項去指導整個編譯鏈接過程
在這裏插入圖片描述
.config文件的格式類似於腳本文件,其中的每一行都是一個配置項,這些配置項被配置的值最終用來決定內核編譯時將哪些內容以什麼方式來編譯

從.config文件的規模可以看出linux內核的可配置項有兩三千個。所以linux內核是高度可配置的,而且linux內核的所有配置項很難全部搞明白。因爲linux內核的配置項太多太繁雜超出了人的大腦能夠記憶和處理的數量級,因此linux內核不像uboot那樣直接手工配置,而是發明了一個圖形化的配置工具menuconfig

3. 內核配置第二步(make menuconfig)

3.1、方法演示

在make menuconfig之前,要確保ncurses安裝。可以使用apt-get install libncurses5-dev
在這裏插入圖片描述
在這裏插入圖片描述

3.2、原理分析

配置第二步的主要目的是爲了通過menuconfig來配置.config文件中的內容。.config中的大部分內容通過make x210ii_qt_defconfig進行了默認的配置,剩下一些細節的內容或者我們想要添加的配置內容都要通過make menuconfig進行添加。

make xxx_defconfig這一步其實是參考別人已經做好的,這樣做有很多好處:減少很多工作量,避開了很多自己不懂的配置項(譬如對內存管理的、調度系統的等模塊的配置項),我們只用管自己需要管的。因此make x210ii_qt_defconfig其實相當於:cp arch/arm/configs/x210ii_qt_defconfig .config,這兩個其實是一個文件,只是複製出來。

make menuconfig其實就是讀取第一步得到的.config,然後給我們一個圖形化的界面,讓我們可以更加容易的找到自己想要修改的配置項,然後更改配置他。

menuconfig方法詳解見第四章:menuconfig原理及使用方法。

4. 內核編譯(make)

當執行make時,即內核根據配置好的內容進行編譯。我們通過make x210ii_qt_defconfig對.config文件進行了第一步的配置,也就是完成了大部分默認的配置工作,然後再利用make menuconfig對.config文件進行一些細微的更改,最終得到的一個完整的.config文件。這個.config文件中記錄了我們設定的配置內容(指導內核編譯什麼不編譯什麼,以什麼方式編譯等),然後.config文件會根據內部的內容信息去影響Makefile文件,利用Makefile文件的條件判斷來決定編譯不編譯哪些模塊,最終影響啓動後的內核。
在這裏插入圖片描述

四、menuconfig原理及使用方法

1. 原理分析

ncurses庫是linux中用來實現文字式的圖形界面,linux內核中使用了ncurses庫來提供menuconfig。scripts\kconfig\lxdialog目錄下的一些c文件就是用來提供menuconfig的那些程序源代碼。

我們說過make menuconfig其實就是讀取.config文件後並通過圖像化方式展示給我們。,這個圖形化界面中間的選擇區中有很多個選擇項,每個選擇項對應.config文件中的一個配置項,每一個選擇項都可以被選擇和配置操作,選擇區中的某些項還包含子目錄的。選擇區太短放不下所有的一個目錄層級的選項,可以用箭頭按鍵的向上箭頭和向下箭頭來上翻和下翻。

那menuconfig是如何顯示菜單的目錄結構呢?
在這裏插入圖片描述
是由內核源碼樹各個目錄下的Kconfig文件來支持的。Kconfig文件中按照一定的格式包含了一個又一個的配置項,每一個配置項在make menuconfig中都會成爲一個菜單項目。而且menuconfig中顯示的菜單目錄結構和源碼目錄中的Kconfig的目錄結構是一樣的。(如果在相應的Kconfig文件中刪除一個config項,則再次make menuconfig時這個項目已經看不到了)

內核源碼目錄樹中每一個Kconfig都會source引入其所有子目錄下的Kconfig,從而保證了所有的Kconfig項目都被包含進menuconfig中。這個也告訴我們:如果你自己在linux內核中添加了一個文件夾,一定要在這個文件夾下創建一個Kconfig文件,然後在這個文件夾的上一層目錄的Kconfig中source引入這個文件夾下的Kconfig文件。

通過menuconfig設置的配置方式保存到哪了呢?
menuconfig或者config後面空格隔開的大寫字母表示的類似於 DM9000 的就是這個配置項的配置項名字,這個字符串前面添加CONFIG_後就構成了.config中的配置項名字。
在這裏插入圖片描述
剛纔已經知道menuconfig的菜單內容來自於Kconfig文件,但是每一個菜單的選擇結果(Y、N、M)卻不是保存在Kconfig文件中的。Kconfig文件是不變的,Kconfig文件只是決定有沒有這個菜單項,並不管這個菜單項的選擇結果。
menuconfig工作時在我們make menuconfig打開時,他會讀取.config文件,並且用.config文件中的配置選擇結果來初始化menuconfig中各個菜單項的選擇值。因此我們改變menuconfig的配置方式之後,會自動保存到.config文件中

總結:菜單項的項目內容從Kconfig文件來,菜單項的選擇值從.config文件來

2. 使用方法

箭頭按鍵導航整個菜單,回車按鍵選擇子菜單(注意選項後面有 —>的選項纔是有子菜單的,沒有這個標識的沒有子菜單),高亮的字母是熱鍵(快捷鍵),鍵盤按鍵Y、N、M三個按鍵的作用分別是將選中模塊編入、去除、模塊化。雙擊ESC表示退出,按下?按鍵可以顯示幫助信息,按下/按鍵可以輸入搜索內容來全局搜索信息(類似於vi中的搜索),[]不可以模塊化,<>的纔可以模塊化

inux內核中一個功能模塊有三種編譯方法:一種是編入、一種去去除、一種是模塊化。所謂編入就是將這個模塊的代碼直接編譯連接到zImage中去,去除就是將這個模塊不編譯鏈接到zImage中模塊化是將這個模塊仍然編譯,但是不會將其鏈接到zImage中,會將這個模塊單獨鏈接成一個內核模塊.ko文件,將來linux系統內核啓動起來後可以動態的加載或卸載這個模塊。
在menuconfig中選項前面的括號裏,*表示編入,空白表示去除,M表示模塊化
在這裏插入圖片描述
(1)tristate意思是三態(3種狀態,對應Y、N、M三種選擇方式),bool是要麼真要麼假(對應Y和N)。所以tristate的意思就是這個配置項可以被三種選擇,bool的意思是這個配置項只能被2種選擇。

(2)depends中文意思是“取決於”或者“依賴於”,所以depends在這裏的意思是:本配置項依賴於另一個配置項。如果那個依賴的配置項爲Y或者M,則本配置項纔有意義;如果依賴的哪個配置項本身被設置爲N,則本配置項根本沒有意義。
depends並不要求依賴的配置項一定是一個,可以是多個,而且還可以有邏輯運算。這種時候只要依賴項目運算式子的裸機結果爲真則依賴就成立。

(3)select表示當該配置被選中時,對應的哪些配置也會被選中。

(4)help 幫助信息,告訴我們這個配置項的含義,以及如何去配置他。

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