linux內核結構和啓動過程

linux內核結構和啓動過程


(以下內容來自教學課件)


一、Linux內核結構

arch

與體系結構相關的代碼。對應於每個支持的體系結構,有一個相應的子目錄如x86、arm等與之對應,相應目錄下有對應的芯片與之對應

drivers

設備驅動代碼,佔整個內核代碼量的一半以上,裏面的每個子目錄對應一類驅動程序,如:char:字符設備、block:塊設備、net:網絡設備等

fs

文件系統代碼,每個支持的文件系統有相應的子目錄,如cramfs,yaffs,jffs2等

include

這裏包括編譯內核所需的大部分頭文件

與平臺無關的頭文件include/linux

各類驅動或功能部件的頭文件(/media、/mtd、/net等)

與體系相關的頭文件arch/arm/include/

與平臺相關的頭文件arch/arm/mach-s5pv210/include/mach

lib

與體系結構無關的內核庫代碼

與體系結構相關的內核庫代碼在arch/arm/lib下

init

內核初始化代碼,其中的main.c中的start_kernel函數是系統引導起來後運行的第1個函數,這是研究內核開始工作的起點

ipc

內核進程間通信代碼

mm

與體系結構無關的內存管理代碼

與處理器體系結構相關的代碼在arch/arm/mm下

kernel

內核管理的核心代碼

net

網絡部分代碼,其每個目錄對應於網絡的一個方面

scripts

存放一些腳本文件,如配置內核時用到的make menuconfig命令

Documentation

內核相關文檔

crypto

常用加密及散列算法,和一些壓縮及CRC校驗算法


二、Linux編程風格

縮進

採用製表符(Tab)進行縮進,而不是空格

禁止製表符和空格混合使用

命名規範

Linux規定名稱中不允許使用混合大小寫字符

單詞之間用下劃線分隔

避免取有疑惑的簡單名稱,如pad(),應該寫成platform_add_devices()

代碼長度

每行儘量不超過80個字符(可進行有意義分行切割)

函數體代碼長度儘量不超過兩屏

函數局部變量儘量不超過十個

根據函數使用頻率和函數體大小可以使用inline聲明,以提高調用效率

註釋

一般情況註釋用於描述代碼可以做什麼和爲什麼要做,儘量不寫實現方式

函數的修改和維護日誌統一集中在文件開頭

其他

指針中的"*"號應靠近變量名,而不是類型關鍵字

函數之間用空行隔開

函數導出申明緊跟在函數定義的下面

等等......


代碼風格的事後修正

indent命令是大多數Linux系統中都帶有的工具,當得到一段與內核編碼風格大相徑庭的代碼時,可以通過這個工具進行調整:

#indent -kr -i8 -ts8 -sob -l80 -ss -bs -psl  <filename>


三、Linux內核啓動引導過程

在瞭解Linux啓動流程之前,首先需要了解Linux鏡像的格式及其產生過程

Image:直接生成並未壓縮的內核,一般用於PC機

zImage:Image的壓縮版,採用gzip進行壓縮,比Image體積小,但啓動時需要進行自解壓,嵌入式系

統中一般採用此種方法

uImage:是u-boot專用的一種內核鏡像格式,它是在zImage的基礎上又添加了一個長度爲0x40的標籤頭,在u-boot啓動時會去掉此頭信息,仍按zImage啓動,頭信息主要用於區分不同格式的內核鏡像

xipImage:片上執行的未壓縮內核,(如norflash等)

(ps:實際應用中由於norflash比較貴,所以大多使用NAND flash作爲存儲器件,而NAND flash不支持片上執行,故xipImage用的比較少)

bootpImage:將內核與根文件系統製作在一起的鏡像


zImage產生過程:vmlinux(內核代碼生成的鏡像)->Image(objcopy對vmlinux二進制化處理)->compressed/vmlinux(壓縮的Image加上head.S和misc.c)->zImage(vmlinux二進制化)


Linux內核的啓動過程大體上可以分爲3個階段:

1、內核解壓(彙編+C)

主要由arch/arm/boot/compressed/對zImage完成解壓,並調用call_kernel跳轉到下階段代碼

2、板級引導階段(彙編)

主要進行cpu和體系結構的檢查、cpu本身的初始化以及頁表的建立等

3、通用內核啓動階段(C語言)

進入init/main.c文件,從start_kernel開始進行內核初始化工作,最後調用rest_init

rest_init()會創建內核第一個線程,並進入線程函數kernel_init()

在kernel_init()中會初始化各種驅動並建立起標準輸入/標準輸出/錯誤輸出,最後調用init_post()

在init_post()中會釋放初始化內存段,標誌着內核啓動完成,並努力尋找一個用戶進程,通過kernel_execve()函數加載,將該進程作爲系統的第一個用戶進程init,進程號爲1,至此內核啓動完成


四、內核的配置與編譯

make menuconfig完成Linux內核配置裁剪

根據配置裁剪的結果配合Makefile完成內核編譯

linux2.6以後的版本是通過每層目錄的Kconfig和Makefile實現了整個Linux內核的分佈式配置

Kconfig:對應內核模塊的配置菜單

Makefile:對應內核模塊的編譯選項


當執行make menuconfig時,配置工具會自動根據根目錄下的ARCH變量讀取arch/$(ARCH)/Kconfig文件來生成配置界面(引用其它目錄的kconfig,通過改變宏定義的方式進行條件編譯),這個文件是所有文件的總入口,其它目錄的Kconfig都由它來引用

配置界面的內容來自於所有目錄的Kconfig, 選擇"*", " ", 或"M"進行條件編譯,對應宏定義在頂層.config文件中

在讀取配置界面的同時,系統會讀取頂層目錄下的.config文件生成所有配置選項的默認值

3、當修改完配置並保存後,系統會更新頂層目錄下的.config文件

4、當執行make時,各層的Makefile會根據.config文件中的編譯選項來決定哪些文件會被編譯到內核中,或編譯成模塊

Kconfig語法格式可以參考具體文件,如:drivers/char/Kconfig

menu "Character devices"

config VT

bool "virtual terminal" if EMBEDDED

depends on !s390

select INPUT

default y

--help--

if you say Y here,you will get support.....

config代表一個選項的開始,最終會出現在.config中(會自動增加一個CONFIG_前綴)

bool代表此選項僅能選中或不選中,bool後面的字符串代表此選項在make menuconfig中的名字

tristate:代表可以選擇編譯、不編譯、編譯成模塊

string:字符串; hex:16進制的數; int:10進制的數

depends on:依賴其餘的選項

default:默認選項值

select:表示當前config被選中時,此選項也被選中

menu/endmenu:表示生成一個菜單

choice/endchoice:表示選擇性的菜單條目

comment:註釋信息,菜單和.config文件中都會出現

source:用於包含其它Kconfig


將自己開發的內核代碼加入到Linux內核中,需要有3個步驟:

1. 確定把自己開發代碼放入到內核合適的位置

2. 把自己開發的功能增加到Linux內核的配置選項中,使用戶能夠選擇此功能

3. 構建或修改Makefile,根據用戶的選擇,將相應的代碼編譯到最終生成的Linux內核中去

比如要把一個key1*5鍵盤驅動添加進內核

步驟如下:

Step1:將s5pv210-key15-simple.c拷到drivers/char/目錄下

Step2: vi driver/char/Kconfig,在Kconfig文件結尾,在endmenu的前面加入一個config選項

config UNSP210_KEY15

bool "key1*5 driver for sunplusedu unsp210 boards"

default y

help

 this is GPIO driver for unsp210 boards.

Step3:make menuconfig(添加配置選項)

   Device driver->

    character devices->

        [*] key1*5 driver for sunplusedu unsp210 boards

Step4: vi driver/char/Makefile添加內容如下:

obj-$(CONFIG_UNSP210_KEY15) += s5pv210-key15-simple.o

Step5:make (更新內核鏡像到開發板)

Step6:交叉編譯測試程序,並放到開發板運行

#arm-linux-gcc key15_test.c -o key15_test



 

 

 

 

 

 


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