2.1 Linux內核發展及演變
- 1991年10月5日 Linus Torvalds創建
- 五個支柱:Unix系統、Minix系統、GNU計划、POSIX標准和Internet
- 每2-3個月更新一次大的版本號
2.2 Linux2.6后的內核特點
- 新的調度器:高負荷下的出色性能,更好的處理器擴展,采用CFS算法,新增調度類:SCHED_DEADLINE,它實現了EDF(最早截止期限優先)算法
- 內核搶占:提高系統的實時性,增強系統的交互性,但也有不可搶占的空間:中斷上下文、軟中斷上下文和自旋鎖的區間,如果打上RT-Preempt補丁,即可支持硬實時。
- 改進線程模型:采用NPTL(本地POSIX線程庫)模型,操作速度極大提高,更加遵循POSIX規范
- 虛擬化內存變化:融合了r-map(反向映射,通過頁結構快速找到頁面的映射)技術,改善虛擬內存在一定大小負載下的性能
- 文件系統:新增基於B樹的Btrfs,是下一代的Linux文件系統
- 音頻:高級Linux音頻體系結構ALSA取代缺陷很多的OSS,支持USB音頻和MIDI設備,並支持雙工重放等功能
- Linux3.7以后實現一個Linux可以適用於所有的arm系統
2.3 Linux內核組成
2.3.1 Linux內核代碼的目錄結構
- arch:和硬件體系結構相關的代碼,每個平台每個目錄
- block:塊設備驅動的I/O調度
- crypto:常用加密和散列算法,還有一些壓縮以及CRC校驗算法
- documentation:內核各部分的通用解釋和注釋
- fs:支持的各種文件系統
- include:內核API級別的頭文件,與系統相關的頭文件放在include/linux子目錄下
- init:內核代碼的初始化代碼
- ipc:進程間通信代碼
- lib:庫文件代碼
- mm:內存管理代碼
- script:配置內核的腳本文件
- usr:用於打包和壓縮的cpio等
2.3.2 內核組成部分
- 進程調度:多數進程是由用戶空間創建,通過系統調用進入內核空間,內核編程是可以啟動內核線程來處理並發任務,這些線程沒有用戶空間
- 內存管理:控制多個進程安全的共享內存區域,通過MMU完成進程從虛擬空間向物理空間的轉換
- 虛擬文件系統:隱藏各個硬件的具體細節,為所有的設備提供了統一的接口,是文件系統的抽象
- 網絡接口:對各種網絡標標准的存取和各種網絡硬件的支持,分為網絡協議和網絡驅動程序
- 進程間通信:信號量、共享內存、消息隊列、管道以及Unix域套接字等
2.3.3 內核空間和用戶空間
- 內核可以進行任何操作,但應用程序被禁止對硬件的直接訪問和對內存的未授權訪問
- 這兩個名詞用來區分程序執行的兩種不同的狀態,他們使用不同的地址空間,用戶空間可以通過系統調用和硬件中斷來訪問內核空間
2.4 內核的編譯及加載
2.4.1 Linux內核配置系統組成
- Makefile:分布於內核源代碼
- 配置文件(Kconfig):給用戶提供配置選項
- 配置工具:命令解析器和配置用戶界面,都是腳本語言
- 通過make config、make menuconfig生成.config文件記錄哪部分被編入內核,哪部分被編譯成模塊
- source可以引入每一層的Kconfig
2.4.2 Kconfig和Makefile
2.4.2.1linux增加程序需要完成以下3項工作
- 將編寫的源碼復制到Linux內核源代碼相應得目錄中
- 在目錄的Kconfig文件中增加關於源代碼相應的編譯配置選項
- 在目錄的Makefile文件中增加對新源代碼的編譯條目
2.4.1.2Makefile語法規則
- 目標定義:用來定義哪些內容要作為模塊編譯,哪些要編譯並鏈接進內核,如:obj-y/m/n += foo.o,obj-$(CONFIG_ISDN) += isdn.o
- 多文件模塊的定義:如下,模塊名為ext2,有balloc.o、dir.o等目標文件最終鏈接生成ext2.o直至ext2.ko文件,是否包含xattr.o、acl.o等文件取決於內核配置文件的配置情況。
obj-$(CONFIG_EXT2_FS) += ext2.o
ext2-y :=balloc.o dir.o file.o ...
ext2-$(CONFIG_EXT2_FS_XATTR) += xattr.o xattr_user.o ...
ext2-$(CONGIF_EXT2_FS_XIP) += xip.o
- 目標層次迭代:如下, 當CONFIG_EXT2_FS的值為y或者m時,kbuild將會把ext2目錄列入向下的目錄中
obj-$(CONFIG_EXT2_FS) += ext2/
2.4.2.3Kconfig語法規則
配置選項
大多數內核配置選項對應的Kconfig中的一個配置選項,”config” 關鍵字定義新的配置選項,之后的幾行代碼定義了誒配置選項的屬性。配置選項的屬性包含:類型,數據提示,依賴關系,選擇關系以及幫助信息、默認值等
config MODVERSIONS
bool "Module versioning support"
help
Usually, you have to use modules compiled with your kernel.
Saying Y here makes it ...
- 每個配置選擇必須包含指定的類型,包括bool,tristate, string, hex 和int,其中tristate和string是基本的類型,其他類型都是基於這兩種類型,類型定以后可以緊跟輸入提示,下面兩段腳本是等價的
bool "Networking support"
和
bool
prompt "Networking support"
- 輸入提示的一般格式為以下形式,其中可選的if用來表示該提示的依賴關系。
prompt <prompt> [if <expr>]
默認值的格式為以下形式,如果用戶不設置對應的選項則配置選項的值就是默認值
default <expr> [if <expr>]
- 依賴關系的格式為以下形式,多重依賴中間要用“&&”間隔
depends on (或者requires) <expr>
依賴關系也可以用在菜單中的其他選項,如下兩段腳本是等價的
bool "foo" if BAR
default y if BAR
和
depends on BAR
bool "foo"
default y
- 選擇關系的格式如下,如果A選擇了B,那么A選中的情況下自動選中B
select <symbol> [if <expr>]
- 數據范圍格式如下
range <symbol> <symbol> [if <expr>]
- Kconfig中的expr定義如下
<expr> :: <symbol>
<symbol> '=' <symbol>
<symbol> '!' <symbol>
'(' <expr> ')'
'!' <expr>
<expr> '&&' <expr>
<expr> '||' <expr>
symbol分為兩類,一類由菜單入口配置項定義的非常數symbol,另一類是作為expr組成部分常數symbol。比如
config SHDMA_R8A73A4
def_bool y
depends on ARCH_R8A73A4 && SH_DMA != n
表達式“depends on ARCH_R8A73A4 && SH_DMA !=n”暗示只有當ARCH_R873A4被選中,而SH_DMA沒有選中的時候,才可能出現這個SHDMA_R8A73A4。
- 為int和hex類型的選項設置可以接受的輸入值范圍,用戶只能輸入大於等於第一個symbol,且小於等於第二個symbol的值
- 幫助信息的格式為
help(或---help---)
開始
...
結束
菜單結構
配置選項在菜單結構的中的位置可有兩種方法決定。
第一種方法為:
menu "Network device support"
depends on NET
config NETDEVICES
...
所有處於“menu”和“endmenu”中的選項都會成為“Network device support”的子菜單,而且,所有的子菜單(config)選項都會繼承父菜單(menu)的依賴關系,比如,“Network device support”對“NET”的依賴會被加載到配置選項NETDEVICES的依賴列表中。
注意:menu后面跟的“Network device support”項僅僅是一個菜單,沒有對應真實的匹配項,也不具備不同的三種狀態,這與config的區別。
另一種方法為:
同過分析依賴關系生成菜單結構。如菜單項在一定程度上依賴與前面的選項,他就能成為該選項的子菜單。如果父選項為“n”,子選項不可見;如果父選項可見,子選項才可見。例如:
config MODULES
bool "Enable loadable module support"
config MODVERSIONS
bool "Set version information on all module symbol"
depends on MODULES
comment "module support disabled"
depends on !MODULES
MODVERSIONS直接依賴MODULES,只有MODULES不為“n”時,該選項才可見。
除此之外,Kconfig中還可能使用“choices … endchoice”、”comment”、“if…endif”這樣的語法結構。其中“choices … endchoice”的結構
choice
<choice options>
<choice block>
endchoice
它定義一個選擇群,其接受的選項(choice potions)可以是前面描述的任何屬性,例如,LDD6410的VGA輸出分辨率可以是1024*768或者是800*600,在driver/video/samsung/Kconfig中就定了如下choice
choice
depends on FB_S3C_VGA
prompt "Select VGA Resolution for S3C Framebuffer"
default FB_S3C_VGA_1024_768
config FB_S3C_VGA_1024_768
bool "1024*768@60Hz"
---help---
TBA
config FB_S3C_VGA_640_480
bool "640*480@60Hz"
---help---
TAB
endchoice
上述例子中,prompt配合choice起到提示的作用。
具體例子見《Linux設備驅動開發詳解》第三版 P72-73
2.4.3 Linux內核的引導
- 上電 => SOC嵌入bootrom 引導=> CPU0上的bootloader
- 其他非CPU0進入WFI狀態等待CPU0喚醒
- CPU0引導bootloader喚醒非CPU0,喚醒后和CPU0都投入運行
- CPU0導致用戶空間的init程序被調用,init派生出其他進程,其他進程在派生出其他進程
- bootloader代表為uboot,其代碼倉庫:http://git.devx.de/u-boot.git/
- zimage:是由未壓縮的解壓算法和壓縮的內核組成,bootloader負責解壓