嵌入式linux启动信息完全注释
?
?
嵌入式linux啟動(dòng)信息完全注釋
from:http://www.embedlinux.cn/ShowPost.asp?ThreadID=377
?
摘要
我們?cè)谶@里討論的是對(duì)嵌入式linux系統(tǒng)的啟動(dòng)過程的輸出信息的注釋,通過我們的討論,大家會(huì)對(duì)嵌入式linux啟動(dòng)過程中出現(xiàn)的、以前感覺熟悉的、但卻又似是而非的東西有一個(gè)確切的了解,并且能了解到這些輸出信息的來龍去脈。
嵌入式linux的啟動(dòng)信息是一個(gè)很值得我們?nèi)ズ煤醚芯康臇|西,它能將一幅縮影圖呈現(xiàn)在我們面前,來指導(dǎo)我們更加深入地理解linux內(nèi)核。
?
關(guān)鍵字:linux,嵌入式,啟動(dòng),bootloader
正文
作為一名嵌入系統(tǒng)開發(fā)者,你一定遇到過下面的情景:
在某論壇上看到一篇帖子,上面貼著嵌入式linux開發(fā)板啟動(dòng)時(shí)的有關(guān)信息,然后大家在帖子里討論著這個(gè)啟動(dòng)過程中出現(xiàn)的問題,隨機(jī)舉例如下:
?
| Linux version 2.4.20-uc0 (root@Local) (gcc version 2.95.3? |
?
上面的這些輸出信息,也可能包括你自己正在做的嵌入式linux開發(fā)板的輸出信息,其中的每一行,每一個(gè)字的含義,你是否深究過,或者說大部分的含義你能確切地知道的?本人想在這里結(jié)合本人在實(shí)踐中一些體會(huì)來和廣大嵌入式linux的開發(fā)者一起讀懂這些信息。
我們?cè)谶@里將以一個(gè)真實(shí)的嵌入式linux系統(tǒng)的啟動(dòng)過程為例,來分析這些輸出信息。啟動(dòng)信息的原始內(nèi)容將用標(biāo)記標(biāo)出,以區(qū)別與注釋。
?
嵌入式linux的啟動(dòng)主要分為兩個(gè)階段:
①???? 第一部分bootloader啟動(dòng)階段
②???? 第二部分linux 內(nèi)核初始化和啟動(dòng)階段
第一節(jié):start_kernel
第二節(jié):用戶模式( user_mode )開始,start_kernel結(jié)束
第三節(jié):加載linux內(nèi)核完畢,轉(zhuǎn)入cpu_idle進(jìn)程
?
第一部分 : bootloader啟動(dòng)
?
| Boot loader v0.12 NOTE: this boot loader is designed to boot kernels made with the 2.4.xx releases bootloader for XV Built at Nov 20 2005 10:12:35 |
?
Bootloader頭信息,版本,編譯時(shí)間等,這個(gè)因不同的bootloader的設(shè)計(jì)而有所不同,由此你能看出bootloader的版本信息,有很多使用的是通用的bootloader,如u-boot,redboot等。
?
| Loaded to 0x90060000 |
?
將bootloader加載到內(nèi)存ram中的0x90060000處,即將bootloader加載到內(nèi)存的高端地址處。
Linux內(nèi)核將被bootloader加載到0x90090000處。
?
?
| Found boot configuration |
?
查找到了啟動(dòng)boot的配置信息
?
?
| Booted from parallel flash |
?
從flash中啟動(dòng)代碼,此處的flash為并行閃存。Flash的分類列舉如下:
閃存分三類:并行,串行,不可擦除。
①并行Parallel flash
NOR Flash,Intel于1988年發(fā)明.隨機(jī)讀取的速度比較快,隨機(jī)按字節(jié)寫,每次可以傳輸8Bit。一般適合應(yīng)用于數(shù)據(jù)/程序的存貯應(yīng)用中.NOR還可以片內(nèi)執(zhí)行(execute-in-place)XIP.寫入和擦除速度很低。
NAND Flash,1989年,東芝公司發(fā)明.是以塊和頁(yè)為單位來讀寫的,不能隨機(jī)訪問某個(gè)指定的點(diǎn).因而相對(duì)來說讀取速度較慢,而擦除和寫入的速度則比較快,每次可以傳輸16Bit,一般適用在大容量的多媒體應(yīng)用中,容量大。如:CF,SM.
②串行Serial Flash 是以字節(jié)進(jìn)行傳輸?shù)?#xff0c;每次可以傳輸1-2Bit.如:MMC,SD,MS卡.串行閃存器件體積小,引腳也少,成本相對(duì)也更低廉。
③不可擦除Mask Rom Flash的特點(diǎn)是一次性錄入數(shù)據(jù),具有不可更改性,經(jīng)常運(yùn)用于游戲和需版權(quán)保護(hù)文件等的錄入。其顯著特點(diǎn)是成本低。
注意:任何flash器件的寫入操作只能在空或已擦除的單元內(nèi)進(jìn)行,所以大多數(shù)情況下,在進(jìn)行寫入操作之前必須先執(zhí)行擦除。NAND器件執(zhí)行擦除操作是十分簡(jiǎn)單的,而NOR則要求在進(jìn)行擦除前先要將目標(biāo)塊內(nèi)所有的位都寫為0。
從上面的信息,我們可以對(duì)flash類型特點(diǎn)有個(gè)比較明確的了解。
?
?
| CPU clock rate: 200 MHz |
?
開發(fā)板上所使用的CPU的主頻為200MHZ.
?
?
| DRAM size is 128MB (128MB/0MB) |
?
動(dòng)態(tài)內(nèi)存ram大小為128M。這里我們列舉一下內(nèi)存的類型及工作原理。
根據(jù)內(nèi)存的工作原理可以劃分出兩種內(nèi)存:DRAM和SRAM
①DRAM表示動(dòng)態(tài)隨機(jī)存取存儲(chǔ)器。這是一種以電荷形式進(jìn)行存儲(chǔ)的半導(dǎo)體存儲(chǔ)器。DRAM中的每個(gè)存儲(chǔ)單元由一個(gè)晶體管和一個(gè)電容器組成。數(shù)據(jù)存儲(chǔ)在電容器中。電容器會(huì)由于漏電而導(dǎo)致電荷丟失,因而DRAM器件是不穩(wěn)定的。為了將數(shù)據(jù)保存在存儲(chǔ)器中,DRAM器件必須有規(guī)律地進(jìn)行刷新。
②SRAM是靜態(tài)的,因此只要供電它就會(huì)保持一個(gè)值。一般而言,SRAM 比DRAM要快,這是因?yàn)镾RAM沒有刷新周期。每個(gè)SRAM存儲(chǔ)單元由6個(gè)晶體管組成,而DRAM存儲(chǔ)單元由一個(gè)晶體管和一個(gè)電容器組成。相比而言,DRAM比SRAM每個(gè)存儲(chǔ)單元的成本要高。照此推理,可以斷定在給定的固定區(qū)域內(nèi)DRAM的密度比SRAM 的密度要大。
?
SRAM常常用于高速緩沖存儲(chǔ)器,因?yàn)樗懈叩乃俾?#xff1b;而DRAM常常用于PC中的主存儲(chǔ)器,因?yàn)槠鋼碛懈叩拿芏取?/p>
在嵌入式系統(tǒng)中使用DRAM內(nèi)存的設(shè)計(jì)比較廣泛。
?
地址輔助說明:
先說明一下內(nèi)存地址數(shù)字情況,主要是為了方便記憶。
可以訪問的內(nèi)存為4G。
0x40000000是1GB處;0x00040000是256K處,0x00020000是128K處,0x90000000是2GB多的地方。
1M->0x00100000,
2M->0x00200000,
8M->0x00800000
16M->0x01000000,
32M->0x02000000
256M->0x10000000
64K->0x00010000
4K->0x00001000
這個(gè)是個(gè)快速記憶的方法,你可以根據(jù)地址中1的位置和其后0的個(gè)數(shù)來快速知道換算后的地址是在多少兆的地方。比如,1的后面5個(gè)0,代表1M的大小,6個(gè)0,代表16M,以此類推。
?
?
ROMFS found at 0x46040000, Volume name = rom 43f291aa
romfs,只讀文件系統(tǒng)所在的地址為:0x46040000 (flash映射后的第3分區(qū))。
卷名為rom。
romfs和rootfs概念上有所區(qū)別。
?
flash在內(nèi)存中的的起始地址為0x46000000,而ROMFS在flash分區(qū)上的起始位置為0x00040000,所以ROMFS在內(nèi)存地址中的位置就為0x46040000。這個(gè)細(xì)節(jié)的部分可以參考flash分區(qū)時(shí)的地方,Creating 3 MTD partitions。
?
romfs中包括kernel和app應(yīng)用,不包括bootloader和firmware信息頭。romfs只讀文件系統(tǒng)里的內(nèi)容有很多種分類方法,我們可以將kernel和app同時(shí)放里面,作為根文件系統(tǒng)下的一個(gè)文件,也可以在flash上另外劃分區(qū)域來分別存放。
?
VFS虛擬文件系統(tǒng)交換器
在linux系統(tǒng)中,目前已經(jīng)開發(fā)出多種文件系統(tǒng),那么如何讓這些文件系統(tǒng)能共存在一個(gè)系統(tǒng)中呢,從linux 2.0開始,引入了虛擬文件系統(tǒng)管理器 VFS的概念。
Linux 下的文件系統(tǒng)主要可分為三大塊:
①???? 一是上層的文件系統(tǒng)的系統(tǒng)調(diào)用,
②???? 二是虛擬文件系統(tǒng)交換器 VFS(Virtual Filesystem Switch),
③???? 三是掛載到 VFS 中的各實(shí)際文件系統(tǒng),例如 ext2,jffs 等。
VFS的確切叫法是Virtual Filesystem Switch虛擬文件系統(tǒng)交換器,這里的VFS中的“S”是指的switch,這個(gè)需要強(qiáng)調(diào)一下的,它很容易被混淆成“system”,如果理解成“system”將是不正確的,請(qǐng)多加注意。
VFS是具體文件系統(tǒng)filesystem的一個(gè)管理器。
VFS是Linux內(nèi)核中的一個(gè)軟件層,一種軟件機(jī)制,它也提供了內(nèi)核中的一個(gè)抽象功能,允許不同的文件系統(tǒng)共存,可以稱它為 Linux 的文件系統(tǒng)管理者,與它相關(guān)的數(shù)據(jù)結(jié)構(gòu)只存在于物理內(nèi)存當(dāng)中。所以在每次系統(tǒng)初始化期間,Linux 都首先要在內(nèi)存當(dāng)中構(gòu)造一棵 VFS 的目錄樹。VFS 中的各目錄其主要用途是用來提供實(shí)際文件系統(tǒng)的掛載點(diǎn)。而rootfs將是這個(gè)目錄樹的根結(jié)點(diǎn)的(root),即 "/"目錄,VFS的結(jié)構(gòu)就是從這個(gè)rootfs開始的。有了VFS,那么對(duì)文件的操作將使用統(tǒng)一的接口,將來通過文件系統(tǒng)調(diào)用對(duì) VFS 發(fā)起的文件操作等指令將被 rootfs 文件系統(tǒng)中相應(yīng)的函數(shù)接口所接管。
?
注意:rootfs并不是一個(gè)具體的文件系統(tǒng)類型,如jffs。它只是一個(gè)理論上的概念。在具體的嵌入系統(tǒng)實(shí)例中,可以將某種具體的文件系統(tǒng)設(shè)置為根文件系統(tǒng)rootfs,如我們可以設(shè)置romfs為根文件系統(tǒng),也可以設(shè)置jffs為根文件系統(tǒng)。
?
這里的ROMFS只讀文件系統(tǒng)只是一種具體的文件系統(tǒng)類型,也是在嵌入系統(tǒng)中經(jīng)常使用到的類型。
?
看完了上面的內(nèi)容,以后你對(duì)出現(xiàn)的類似“kernel Panic:VFS:Unable to mount root fs on 0:00”的含義應(yīng)該已經(jīng)了解了。其中“VFS:”就是虛擬文件系統(tǒng)管理器操作時(shí)的輸出信息了。
?
| File linux.bin.gz found |
?
linux kernel內(nèi)核文件名,它是在只讀文件系統(tǒng)romfs上的一個(gè)組成部分。
?
| Unzipping image from 0x4639DE60 to 0x90090000, size = 1316021 |
?
將romfs中的linux kernel解壓縮到0x90090000,之后會(huì)從這個(gè)內(nèi)存地址啟動(dòng)內(nèi)核。romfs為壓縮格式文件,使用壓縮的只讀文件系統(tǒng),是為了保持制作出來的整個(gè)系統(tǒng)所占用的flash空間減小。這個(gè)內(nèi)核的大小為1.3M左右,這也是目前大多數(shù)嵌入系統(tǒng)所使用的方法。
?
| Inptr = 0x00000014(20) Inflating.... |
?
釋放,解壓中。。。(變大,充氣, 膨脹)
?
| Outcnt = 0x0030e7c8(3205064) Final Inptr = 0x001414ad(1316013) Original CRC = 0xcbd73adb Computed CRC = 0xcbd73adb |
?
做釋放后的CRC檢查
?
| Boot kernel at 0x90090000 with ROMFS at 0x46040000 |
?
kernel已經(jīng)被從romfs中釋放到內(nèi)存地址0x90090000處,可以跳轉(zhuǎn)到此處啟動(dòng)kernel了,這里是指定的kernel的起始地址
?
| Press 'enter' to boot |
?
系統(tǒng)等待啟動(dòng),后面將看到linux kernel的啟動(dòng)過程了。
?
第二部分 : linux內(nèi)核初始化以及啟動(dòng)
第一節(jié):start_kernel
Linux的源代碼可以從www.kernel.org得到,或者你可以查看linux代碼交叉引用網(wǎng)站:http://lxr.linux.no/?進(jìn)行在線的代碼查看,這是一個(gè)很好的工具網(wǎng)站。
在start_kernel中將調(diào)用到大量的init函數(shù),來完成內(nèi)核的各種初始化。如:
page_address_init();
sched_init();
page_alloc_init();
init_IRQ();
softirq_init();
console_init();
calibrate_delay();
vfs_caches_init(num_physpages);
rest_init();
具體內(nèi)容可以參考[http://lxr.linux.no/source/init/main.c]
?
| Linux version 2.4.22-uc0 (root@local) (gcc version 2.95.3 20010315 (release)) #33 .?1.. 20 12:09:106 |
?
上面的代碼輸出信息,是跟蹤linux代碼分析后得到的,進(jìn)入init目錄下的main.c的start_kernel啟動(dòng)函數(shù).
嵌入式linux使用的是linux內(nèi)核版本為2.4.22
linux source code代碼中start_kernel中輸出的linux_banner信息。這個(gè)信息是每個(gè)linux kernel都會(huì)打印一下的信息,如果你沒有把這句去掉的話。
?
Found bootloader memory map at 0x10000fc0.
bootloader經(jīng)過內(nèi)存映射后的地址為:0x10000fc0, 按上面的地址換算方法,1后面有7個(gè)0,那么虛擬地址256M左右處。
?
| Processor: ARM pt110 revision 0 |
?
pT110是ARM微處理器arm核的一種,另一種為pT100。此處為顯示ARM的類型。
?
| On node 0 totalpages: 20480 zone(0): 20480 pages. zone(0): Set minimum memory threshold to 12288KB Warning: wrong zone alignment (0x90080000, 0x0000000c, 0x00001000) zone(1): 0 pages. zone(2): 0 pages. |
?
預(yù)留內(nèi)存大小,在節(jié)點(diǎn)0上總共20頁(yè), zone(0) 設(shè)置最小內(nèi)存為12MB, zone(1)和zone(2)為0頁(yè)。警告:對(duì)齊不正確
?
| Kernel command line: root=/dev/mtdblock3 |
?
Kernel 啟動(dòng)命令設(shè)為:/dev/mtdblock3(在后面的說明中會(huì)看到mtdblock3是指的flash上的romfs分區(qū)。),用來指定根文件系統(tǒng)所在的位置,kernel會(huì)將塊設(shè)備mtdblock3當(dāng)作文件系統(tǒng)來處理。
也就是說,內(nèi)核會(huì)根據(jù)上面的kernel命令行,知道只讀文件系統(tǒng)romfs將是根文件系統(tǒng)rootfs。
start_kernel(void)中輸出的上面的這句信息。
這行命令是在linux內(nèi)核啟動(dòng)過程中都會(huì)輸出的一句。
?
| Console: colour dummy device 80x30 |
?
代碼中console_init()的輸出信息, 顯示控制臺(tái)屬性:一般使用VGA text console,標(biāo)準(zhǔn)是80 X 25行列的文本控制臺(tái),這里是對(duì)屬性進(jìn)行了設(shè)置。
?
| serial_xx: setup_console @ 115 |
?
串口設(shè)置值為115200,此為波特率輸出信息。對(duì)串口設(shè)置的信息做一個(gè)打印的動(dòng)作,在調(diào)試時(shí)會(huì)非常有用。
?
| Calibrating delay loop... 82.94 BogoMIPS |
?
Calibrate:校準(zhǔn), 進(jìn)入時(shí)延校準(zhǔn)循環(huán)。檢查CPU的MIPS(每秒百萬條指令),Bogo是Bogus(偽)的意思。這里是對(duì)CPU進(jìn)行一個(gè)實(shí)時(shí)測(cè)試,來得到一個(gè)大體的MIPS數(shù)值
Bogomips,是由linus Torvalds寫的, 是Linux操作系統(tǒng)中衡量計(jì)算機(jī)處理器運(yùn)行速度的一種尺度。提供這種度量的程序被稱為BogoMips,當(dāng)啟動(dòng)計(jì)算機(jī)時(shí),BogoMips能顯示系統(tǒng)選項(xiàng)是否處于最佳性能。
linux內(nèi)核中有一個(gè)函數(shù)calibrate_delay(),它可以計(jì)算出cpu在一秒鐘內(nèi)執(zhí)行了多少次一個(gè)極短的循環(huán),計(jì)算出來的值經(jīng)過處理后得到BogoMIPS值
你可以將計(jì)算機(jī)的bogomips與計(jì)算機(jī)處理器的bogomips進(jìn)行比較。Torvalds稱這個(gè)程序?yàn)锽ogoMips來暗示兩臺(tái)計(jì)算機(jī)間的性能度量是錯(cuò)誤的,因?yàn)椴⒎撬衅鹱饔靡蛩囟寄鼙伙@示出來或被認(rèn)可。盡管計(jì)算機(jī)基準(zhǔn)中經(jīng)常用到MIPS,但環(huán)境的變化容易導(dǎo)致度量的錯(cuò)誤。Bogomips能測(cè)出一秒鐘內(nèi)某程序運(yùn)行了多少次。
察看/proc/cpuinfo文件中的最后一行也能得到這個(gè)數(shù)值。
上面這個(gè)輸出,在所有的linux系統(tǒng)啟動(dòng)中都會(huì)打印出來。
?
進(jìn)入內(nèi)存初始化
mem_init(void), [arch/i386/mm/init.c]
?
| Memory: 80MB = 80MB total Memory: 76592KB available (1724K code, 2565K data, 72K init) |
?
當(dāng)前內(nèi)存使用情況,將列出總的內(nèi)存大小, 及分配給內(nèi)核的內(nèi)存大小:包括代碼部分,數(shù)據(jù)部分,初始化部分,總共剛好4M。請(qǐng)留意此處的內(nèi)核的內(nèi)存大小的各個(gè)值。
?
進(jìn)入虛擬文件系統(tǒng)VFS初始化
vfs_caches_init()
?
| Dentry cache hash table entries: 16384 (order: 5, 131072 bytes) Inode cache hash table entries: 8192 (order: 4, 65536 bytes) Mount cache hash table entries: 512 (order: 0, 4096 bytes) Buffer cache hash table entries: 4096 (order: 2, 16384 bytes) Page-cache hash table entries: 32768 (order: 5, 131072 bytes) |
?
名詞:
①???? Dentry:目錄數(shù)據(jù)結(jié)構(gòu)
②???? Inode:i節(jié)點(diǎn)
③???? Mount cache:文件系統(tǒng)加載緩沖
④???? buffer cache:內(nèi)存緩沖區(qū)
⑤???? Page Cache:頁(yè)緩沖區(qū)
Dentry目錄數(shù)據(jù)結(jié)構(gòu)(目錄入口緩存),提供了一個(gè)將路徑名轉(zhuǎn)化為特定的dentry的一個(gè)快的查找機(jī)制,Dentry只存在于RAM中;
i節(jié)點(diǎn)(inode)數(shù)據(jù)結(jié)構(gòu)存放磁盤上的一個(gè)文件或目錄的信息,i節(jié)點(diǎn)存在于磁盤驅(qū)動(dòng)器上;存在于RAM中的i節(jié)點(diǎn)就是VFS的i節(jié)點(diǎn),dentry所包含的指針指向的就是它;
buffer cache內(nèi)存緩沖區(qū),類似kupdated,用來在內(nèi)存與磁盤間做緩沖處理;
Page Cache 用來加快對(duì)磁盤上映像和數(shù)據(jù)的訪問。
在內(nèi)存中建立各個(gè)緩沖hash表,為kernel對(duì)文件系統(tǒng)的訪問做準(zhǔn)備。
VFS(virtual filesystem switch)虛擬文件切換目錄樹有用到類似這樣的結(jié)構(gòu)表。
上面的輸出信息,在一般的linux啟動(dòng)過程中都會(huì)看到。
?
| POSIX conformance testing by UNIFIX |
?
conformance:順應(yīng), 一致。即POSIX適應(yīng)性檢測(cè)。UNIFIX是一家德國(guó)的技術(shù)公司,Linux 原本要基于 POSIX.1 的, 但是 POSIX 不是免費(fèi)的, 而且 POSIX.1 證書相當(dāng)昂貴. 這使得 Linux 基于 POSIX 開發(fā)相當(dāng)困難. Unifix公司(Braunschweig, 德國(guó)) 開發(fā)了一個(gè)獲得了 FIPS 151-2 證書的 Linux 系統(tǒng). 這種技術(shù)用于 Unifix 的發(fā)行版 Unifix Linux 2.0 和 Lasermoon 的 Linux-FT。
在2.6的內(nèi)核中就將上面的這句輸出給拿掉了。
?
第二節(jié):用戶模式( user_mode )開始,start_kernel結(jié)束
?
| PCI: bus0: Fast back to back transfers disabled PCI: Configured XX as a PCI slave with 128MB PCI memory PCI: Each Region size is 16384KB PCI: Reserved memory from 0x10080000 to 0x15080000 for DMA and mapped to 0x12000000 |
?
設(shè)備的初始化 init()--->do_basic_init()--->pci_init(),初始化PCI,檢測(cè)系統(tǒng)的PCI設(shè)備。
?
| Linux NET4.0 for Linux 2.4 Based upon Swansea University Computer Society NET3.039 |
?
英國(guó)威爾士,斯旺西大學(xué)的NET3.039, TCP/IP 協(xié)議棧
此信息,在linux啟動(dòng)過程中都會(huì)出現(xiàn)。
?
| Initializing RT netlink socket |
?
對(duì)Socket的初始化,socket_init(),Netlink 一種路由器管理協(xié)議(linux-2.4.22/net/core/Rtnetlink.c,Routing netlink socket interface: protocol independent part。 其中RT是route路由的意思。這句輸出是在create產(chǎn)生rtnetlink的socket套接字時(shí)的一個(gè)調(diào)試輸出。)
此信息,在linux啟動(dòng)過程中都會(huì)出現(xiàn)。
?
| Starting kswapd |
?
啟動(dòng)交換守護(hù)進(jìn)程kswapd,進(jìn)程IO操作例程kpiod
kswapd可以配合kpiod運(yùn)行。進(jìn)程有時(shí)候無事可做,當(dāng)它運(yùn)行時(shí)也不一定需要把其所有的代碼和數(shù)據(jù)都放在內(nèi)存中。這就意味著我們可以通過把運(yùn)行中程序不用的內(nèi)容切換到交換分區(qū)來更好的是利用內(nèi)存。大約每隔1秒,kswapd醒來并檢查內(nèi)存情況。如果在硬盤的東西要讀入內(nèi)存,或者內(nèi)存可用空間不足,kpiod就會(huì)被調(diào)用來做移入/移出操作。kswapd負(fù)責(zé)檢查,kpiod負(fù)責(zé)移動(dòng)。
?
| Journalled Block Device driver loaded |
?
加載日志塊設(shè)備驅(qū)動(dòng)。
日志塊設(shè)備是用來對(duì)文件系統(tǒng)進(jìn)行日志記錄的一個(gè)塊設(shè)備。日志文件系統(tǒng)是在傳統(tǒng)文件系統(tǒng)的基礎(chǔ)上,加入文件系統(tǒng)更改的日志記錄。
它的設(shè)計(jì)思想是:跟蹤記錄文件系統(tǒng)的變化,并將變化內(nèi)容記錄入日志。日志文件系統(tǒng)在磁盤分區(qū)中保存有日志記錄,寫操作首先是對(duì)記錄文件進(jìn)行操作,若整個(gè)寫操作由于某種原因(如系統(tǒng)掉電)而中斷,系統(tǒng)重啟時(shí),會(huì)根據(jù)日志記錄來恢復(fù)中斷前的寫操作。在日志文件系統(tǒng)中,所有的文件系統(tǒng)的變化都被記錄到日志,每隔一定時(shí)間,文件系統(tǒng)會(huì)將更新后的元數(shù)據(jù)及文件內(nèi)容寫入磁盤。在對(duì)元數(shù)據(jù)做任何改變以前,文件系統(tǒng)驅(qū)動(dòng)程序會(huì)向日志中寫入一個(gè)條目,這個(gè)條目描述了它將要做些什么,然后它修改元數(shù)據(jù)。
?
| devfs: v1.12c (20020818) Richard Gooch (rgooch@atnf.csiro.au) devfs: boot_options: 0x1 |
?
Devfs模塊的輸出信息。
設(shè)備文件系統(tǒng)devfs,版本1.12c,
?
| pty: 256 Unix98 ptys configured |
?
Pty模塊的輸出信息,與控制臺(tái)操作有關(guān)的設(shè)置。
將通過 devpts 文件系統(tǒng)使用 Unix98 PTYs,(Pseudo-ttys (telnet etc) device是偽ttys設(shè)備的縮寫。
①????????????? TTY(/dev/tty)是TeleTYpe的一個(gè)老縮寫,為用戶輸入提供不同控制臺(tái)的設(shè)備驅(qū)動(dòng)程序。它的名字來源于實(shí)際掛接到 UNIX系統(tǒng)的、被稱為電傳打字機(jī)(teletype)的終端。在Linux下,這些文件提供對(duì)虛擬控制臺(tái)的支持,可以通過按<Alt-F1>到<Alt-F6>鍵來訪問這些虛擬控制臺(tái)。這些虛擬控制臺(tái)提供獨(dú)立的、同時(shí)進(jìn)行的本地登錄對(duì)話過程
②????????????? ttys(/dev/ttys)是計(jì)算機(jī)終端的串行接口。/dev/ttyS0對(duì)應(yīng)MS-DOS下的 COM1。
?
使用 make dev腳本MAKEDEV來建立pty文件。這樣系統(tǒng)內(nèi)核就支持Unix98風(fēng)格的pty了。在進(jìn)行Telnet登錄時(shí)將要用到/dev/pty設(shè)備。 pty是偽終端設(shè)備,在遠(yuǎn)程登錄等需要以終端方式進(jìn)行連接,但又并非真實(shí)終端的應(yīng)用程序中必須使用這種設(shè)備,如telnet或xterm等程序。Linux 2.2以后增添了UNIX98風(fēng)格的Pty設(shè)備,它使用一個(gè)新的文件系統(tǒng)(devpts針對(duì)偽終端的文件系統(tǒng))和一個(gè)克隆的設(shè)備cloning device來實(shí)現(xiàn)其功能。
linux-2.4.22/drivers/char/Pty.c, 在devfs_mk_dir (NULL, "pts", NULL);時(shí)會(huì)輸出上面的信息。
?
?
| loop: loaded (max 8 devices) |
?
加載返還塊設(shè)備驅(qū)動(dòng),最多支持8個(gè)設(shè)備
?
?
| 8139too Fast Ethernet driver 0.9.27 eth0: RealTek RTL8139 at 0x60112000, 00:10:0d:42:a0:03, IRQ 14 eth0: Identified 8139 chip type 'RTL-8100B/8139D' |
?
網(wǎng)卡驅(qū)動(dòng),基地址為:0x60112000, MAC地址:00:10:0d:42:a0:03, 中斷號(hào):14
RTL8139 的接收路徑設(shè)計(jì)成一個(gè)環(huán)形緩沖區(qū)(一段線性的內(nèi)存,映射成一個(gè)環(huán)形內(nèi)存)。當(dāng)設(shè)備接收到數(shù)據(jù)時(shí),數(shù)據(jù)的內(nèi)容就保存在這個(gè)環(huán)形緩沖區(qū)內(nèi)并更新下個(gè)存儲(chǔ)數(shù)據(jù)的地址(第一個(gè)數(shù)據(jù)包的開始地址+第一個(gè)數(shù)據(jù)包的長(zhǎng)度)。設(shè)備會(huì)一直保留緩沖區(qū)內(nèi)的數(shù)據(jù)直到整個(gè)緩沖區(qū)耗盡。這樣,設(shè)備會(huì)再次重寫緩沖區(qū)內(nèi)起始位置的內(nèi)容,就像一個(gè)環(huán)那樣。
從 2.2 版內(nèi)核升級(jí)到 2.4 版時(shí), RTL-8139 支持模塊已不再叫 rtl8139,而叫它 8139too,現(xiàn)在你再看到8139too就不會(huì)不明白它的來由了吧。
?
| SCSI subsystem driver Revision: 1.00 |
?
USB設(shè)備信息,USB會(huì)被當(dāng)做SCSI來處理。
?
| mumk_register_tasklet: (1) tasklet 0x905bf9c0 status @0x9025e974 |
?
軟中斷信息輸出。Tasklet是在2.4中才出現(xiàn),它是為了更好地利用多CPU。
?
?
| Probing XX Flash Memory |
?
探測(cè) XX的閃存(Flash Memory),"NOR NAND Flash Memory Technology"
?
Amd/Fujitsu Extended Query Table v1.3 at 0x0040
number of CFI chips: 1
AMD與富士通合資設(shè)立的Flash供貨商Spansion。AMD因獲利不佳,已經(jīng)退出Flash市場(chǎng),后續(xù)由Spansion合資公司經(jīng)營(yíng).主要生產(chǎn)NOR類型的flash,特點(diǎn)是容量小,速度快。Spansion商標(biāo)的flash,在我們開發(fā)中會(huì)經(jīng)常看到。以后大家看到Spansion的芯片,就能了解到它和AMD還有富士通的來龍去脈了。
Common flash Interface (CFI)是指一個(gè)統(tǒng)一的flash訪問接口,表示這種flash是這種接口類型的。
?
| Using buffer write method |
?
使用flash寫緩沖方式
flash提供了寫B(tài)UFFER的命令來加快對(duì)flash上塊的操作。對(duì)Flash擦除和寫數(shù)據(jù)是很慢的。如果用寫B(tài)UFFER的命令會(huì)快一點(diǎn)。據(jù)手冊(cè)上說,會(huì)快20倍。Buffer Size :5 bytes的buffer緩沖不是每個(gè)塊都有,是整個(gè)flash只有一個(gè)5 bytes的buffer,用寫B(tài)UFFER命令對(duì)所有的塊進(jìn)行寫操作,都要用同一個(gè)buffer,寫B(tài)uffer是主要檢查buffer是否available,其實(shí)buffer起緩沖作用,來提高工作效率。
比如某flash有128個(gè)128K字節(jié)塊。允許用戶對(duì)任意塊進(jìn)行字節(jié)編程和寫緩沖器字節(jié)編程操作,每字節(jié)編程時(shí)間為210μs;若采用寫緩沖器字節(jié)編程方式,32字節(jié)編程共需218μs,每字節(jié)編程時(shí)間僅為6.8μs。芯片的塊擦除時(shí)間為1s,允許在編程或塊擦除操作的同時(shí)進(jìn)行懸掛中斷去進(jìn)行讀操作,待讀操作完成后,寫入懸掛恢復(fù)命令,再繼續(xù)編程或塊擦除。
?
?
| Creating 3 MTD partitions on "XX mapped flash": 0x00000000-0x00020000 : "BootLoader" 0x00020000-0x00040000 : "Config" 0x00040000-0x01000000 : "Romfs" |
?
此處為重要信息部分,需要特別留意。
在內(nèi)存中映射過的flash,創(chuàng)建三個(gè)MTD分區(qū):
flash上的內(nèi)容將被映射到內(nèi)存中的對(duì)應(yīng)地址
前128K為BootLoader--->0x00000000-0x00020000
接著的128K為系統(tǒng)配置信息Config存放的位置--->0x00020000-0x00040000
再后面的 16M - 2X128K 為romfs的存放處.--->0x00040000-0x01000000
上面的內(nèi)容,大家可以根據(jù)前面的換算公式得到。
?
A> 編譯的bootloader一般大小約50K左右;
B> 在此處就知道了配置信息config是放在第2分區(qū)中的;
C> 制作的romfs的大小,一般為8M或10M左右,所以能放得下;
?
嵌入式Linux內(nèi)核的塊設(shè)備驅(qū)動(dòng):
對(duì)于linux 的根文件系統(tǒng),目前有三種塊設(shè)備的驅(qū)動(dòng)可以選擇,它們分別是:
a) Blkmem 驅(qū)動(dòng)
b) MTD 驅(qū)動(dòng)
c) RAM disk 驅(qū)動(dòng)
Blkmem 驅(qū)動(dòng)是專門為嵌入式linux 開發(fā)的一種塊設(shè)備驅(qū)動(dòng),它是嵌入式linux系統(tǒng)中最為古老和通用的塊設(shè)備驅(qū)動(dòng)。它原理相對(duì)簡(jiǎn)單但是配置比較復(fù)雜,需要根據(jù)你即的Flash的分區(qū)使用情況來修改代碼。當(dāng)然修改的結(jié)果是它可以對(duì)一些NOR型的Flash進(jìn)行讀寫操作。不過目前支持的Flash類型不夠多。如果新加入對(duì)一種Flash的支持需要作的工作量比較大。
Linux的MTD驅(qū)動(dòng)是標(biāo)準(zhǔn)Linux的Flash驅(qū)動(dòng)。它支持大量的設(shè)備,有足夠的功能來定義Flash的分區(qū),進(jìn)行地址映射等等。使用MTD你可以在一個(gè)系統(tǒng)中使用不同類型的Flash。它可以將不同的Flash組合成一個(gè)線性的地址讓你來使用。
在標(biāo)準(zhǔn)的Linux 2.4內(nèi)核中MTD有一系列的選項(xiàng),你可以根據(jù)個(gè)人系統(tǒng)的需要來選擇,定制。
另外一種選擇就是RAM disk 驅(qū)動(dòng)。在PC上它經(jīng)常用于沒有硬盤的Linux的啟動(dòng)過程。它和Flash沒有直接的關(guān)系。不過當(dāng)Flash上啟動(dòng)的是經(jīng)過壓縮的內(nèi)核時(shí)。RAM disk 可以作為根文件系統(tǒng)。
MTD 驅(qū)動(dòng)提供了對(duì)Flash強(qiáng)大的支持,你通過它甚至可以在Flash上運(yùn)行一個(gè)可以讀寫的真正的文件系統(tǒng),比如JFFS2。而Blkmem驅(qū)動(dòng)則望塵莫及。
?
| NET4: Linux TCP/IP 1.0 for NET4.0 |
?
調(diào)用inet_init [ linux-2.4.22/net/ipv4/Af_inet.c ]時(shí)的輸出信息, 在啟動(dòng)過程中被socket.c調(diào)用到。
?
| IP Protocols: ICMP, UDP, TCP, IGMP |
?
列出可以支持的IP協(xié)議,此處為kernel源代碼inet_add_protocol(p);的輸出。
在linux啟動(dòng)過程中,都會(huì)看到這句的輸出。
?
| IP: routing cache hash table of 512 buckets, 4Kbytes |
?
IP路由代碼的輸出信息。
ip_rt_init [ linux-2.4.22/net/ipv4\Route.c ],Set the IP module up,路由緩沖hash表
?
| TCP: Hash tables configured (established 8192 bind 8192) |
?
TCP協(xié)議初始化輸出信息。tcp_init [ linux-2.4.22/net/ipv4/Tcp.c ],
?
| NET4: Unix domain sockets 1.0/SMP for Linux NET4.0. |
?
UNIX網(wǎng)絡(luò)協(xié)議信息。
af_unix_init[ linux-2.4.22/net/unix/Af_unix.c ], 多種連接的一種(IPv4, UNIX domain sockets, IPv6和IrDA). SMP 對(duì)稱多處理器—Symmetrical Multi Processing,這里主要是指UNIX的一些網(wǎng)絡(luò)協(xié)議.
?
上面的關(guān)于網(wǎng)絡(luò)的輸出信息是在linux啟動(dòng)信息中都會(huì)出現(xiàn)的。
加載各種文件系統(tǒng)
?
| cramfs: wrong magic |
?
會(huì)出現(xiàn)“cramfs: wrong magic”,別擔(dān)心這沒有什么害處,這個(gè)是kernel的書寫bug,在2.6中有修改之,它是一個(gè)警告信息,用來檢查cramfs的superblock超級(jí)塊的。superblock也是VFS要用到的數(shù)據(jù)結(jié)構(gòu)。
代碼linux-2.4.22/fs/cramfs/Inode.c:
?
| 2.4 cramfs_read_super(。。。) /* Do sanity checks on the superblock */ ?????? if (super.magic != CRAMFS_MAGIC) { ????????????? /* check at 512 byte offset */ ????????????? memcpy(&super, cramfs_read(sb, 512, sizeof(super)), sizeof(super)); ?????? ?????? if (super.magic != CRAMFS_MAGIC) { ???????????????????? printk(KERN_ERR "cramfs: wrong magic/n"); ???????????????????? goto out; ????????????? } ?????? } |
?
?
?
| 2.6 if (super.magic != CRAMFS_MAGIC) { ???????????????????????? if (!silent) ???????????????????????????????? printk(KERN_ERR "cramfs: wrong magic/n"); ???????????????????????? goto out; ???????????????? } |
?
超級(jí)塊是文件系統(tǒng)的“頭部”。它包含文件系統(tǒng)的狀態(tài)、尺寸和空閑磁盤塊等信息。如果損壞了一個(gè)文件系統(tǒng)的超級(jí)塊(例如不小心直接將數(shù)據(jù)寫到了文件系統(tǒng)的超級(jí)塊分區(qū)中),那么系統(tǒng)可能會(huì)完全不識(shí)別該文件系統(tǒng),這樣也就不能安裝它了,即使采用e2fsck 命令也不能處理這個(gè)問題。
?
Cramfs文件系統(tǒng):
cramfs 是 Linus Torvalds 本人開發(fā)的一個(gè)適用于嵌入式系統(tǒng)的小文件系統(tǒng)。由于它是只讀的,所以,雖然它采取了 zlib 做壓縮,但是它還是可以做到高效的隨機(jī)讀取。 cramfs 不會(huì)影響系統(tǒng)讀取文件的速度,又是一個(gè)高度壓縮的文件系統(tǒng)。
我們制作image文件之后,我們還要考慮怎樣才能在系統(tǒng)運(yùn)行的時(shí)候,把這個(gè) image 文件 mount 上來,成為一個(gè)可用的文件系統(tǒng)。由于這個(gè) image 文件不是一個(gè)通常意義上的 block 設(shè)備,我們必須采用 loopback 設(shè)備來完成這一任務(wù),如:
mount -o loop -t cramfs /usr.img /usr
這樣,就可以經(jīng)由 loopback 設(shè)備,把 usr.img 這個(gè) cramfs 的 image 文件 mount 到 /usr 目錄上去了。內(nèi)核中需要對(duì)loopback這個(gè)設(shè)備的支持。
cramfs 的壓縮效率一般都能達(dá)到將近 50%。
Cramfs通過優(yōu)化索引節(jié)點(diǎn)表的尺寸和除去傳統(tǒng)文件系統(tǒng)中文件之間的空間浪費(fèi)來達(dá)到節(jié)約空間的目的。它還使用了zlib壓縮,實(shí)現(xiàn)優(yōu)于2:1的壓縮比例。解壓縮過程的系統(tǒng)開銷并不是很大,因?yàn)镃ramfs支持指定單塊的解壓,而并不必解壓縮整個(gè)文件。
Cramfs不僅能節(jié)省空間,還能避免非正常關(guān)機(jī)導(dǎo)致的等待fsck或手工進(jìn)行fsck的麻煩。它通過只讀的方式達(dá)到這一目的。
RamDisk有三種實(shí)現(xiàn)方式:
在Linux中可以將一部分內(nèi)存mount為分區(qū)來使用,通常稱之為RamDisk,分為:
Ramdisk, ramfs, tmpfs.
① 第一種就是傳統(tǒng)意義上的,可以格式化,然后加載。
這在Linux內(nèi)核2.0/2.2就已經(jīng)支持,其不足之處是大小固定,之后不能改變。
為了能夠使用Ramdisk,我們?cè)诰幾g內(nèi)核時(shí)須將block device中的Ramdisk支持選上,它下面還有兩個(gè)選項(xiàng),一個(gè)是設(shè)定Ramdisk的大小,默認(rèn)是4096k;另一個(gè)是initrd的支持。
如果對(duì)Ramdisk的支持已經(jīng)編譯進(jìn)內(nèi)核,我們就可以使用它了:
首先查看一下可用的RamDisk,使用ls /dev/ram*
首先創(chuàng)建一個(gè)目錄,比如test,運(yùn)行mkdir /mnt/test;
然后對(duì)/dev/ram0 創(chuàng)建文件系統(tǒng),運(yùn)行mke2fs /dev/ram0;
最后掛載 /dev/ram0,運(yùn)行mount /dev/ram /mnt/test,就可以象對(duì)普通硬盤一樣對(duì)它進(jìn)行操作了。
② 另兩種則是內(nèi)核2.4才支持的,通過Ramfs或者Tmpfs來實(shí)現(xiàn):
它們不需經(jīng)過格式化,用起來靈活,其大小隨所需要的空間而增加或減少。
Ramfs顧名思義是內(nèi)存文件系統(tǒng),它處于虛擬文件系統(tǒng)(VFS)層,而不像ramdisk那樣基于虛擬在內(nèi)存中的其他文件系統(tǒng)(ex2fs)。
因而,它無需格式化,可以創(chuàng)建多個(gè),只要內(nèi)存足夠,在創(chuàng)建時(shí)可以指定其最大能使用的內(nèi)存大小。
如果你的Linux已經(jīng)將Ramfs編譯進(jìn)內(nèi)核,你就可以很容易地使用Ramfs了。創(chuàng)建一個(gè)目錄,加載Ramfs到該目錄即可:
# mkdir /testRam
# mount -t ramfs none /testRAM
缺省情況下,Ramfs被限制最多可使用內(nèi)存大小的一半。可以通過maxsize(以kbyte為單位)選項(xiàng)來改變。
# mount -t ramfs none /testRAM -o maxsize=2000 (創(chuàng)建了一個(gè)限定最大使用內(nèi)存為2M的ramdisk)
③ Tmpfs是一個(gè)虛擬內(nèi)存文件系統(tǒng),它不同于傳統(tǒng)的用塊設(shè)備形式來實(shí)現(xiàn)的Ramdisk,也不同于針對(duì)物理內(nèi)存的Ramfs。
Tmpfs可以使用物理內(nèi)存,也可以使用交換分區(qū)。在Linux內(nèi)核中,虛擬內(nèi)存資源由物理內(nèi)存(RAM)和交換分區(qū)組成,這些資源是由內(nèi)核中的虛擬內(nèi)存子系統(tǒng)來負(fù)責(zé)分配和管理。
Tmpfs向虛擬內(nèi)存子系統(tǒng)請(qǐng)求頁(yè)來存儲(chǔ)文件,它同Linux的其它請(qǐng)求頁(yè)的部分一樣,不知道分配給自己的頁(yè)是在內(nèi)存中還是在交換分區(qū)中。同Ramfs一樣,其大小也不是固定的,而是隨著所需要的空間而動(dòng)態(tài)的增減。
使用tmpfs,首先你編譯內(nèi)核時(shí)得選擇"虛擬內(nèi)存文件系統(tǒng)支持(Virtual memory filesystem support)" 。
然后就可以加載tmpfs文件系統(tǒng)了:
# mkdir -p /mnt/tmpfs
# mount tmpfs /mnt/tmpfs -t tmpfs
同樣可以在加載時(shí)指定tmpfs文件系統(tǒng)大小的最大限制:
# mount tmpfs /mnt/tmpfs -t tmpfs -o size=32m
?
| FAT: bogus logical sector size 21072 |
?
具體的文件系統(tǒng)FAT格式。
虛擬邏輯扇區(qū)大小為20K,linux-2.4.22/fs/fat/Inode.c。
在初始化MS-DOS文件系統(tǒng)時(shí),讀MS-DOS文件系統(tǒng)的superblock,函數(shù)fat_read_super中輸出的上面的信息。
?
| UMSDOS: msdos_read_super failed, mount aborted. |
?
UMSDOS:一種文件系統(tǒng),特點(diǎn)容量大但相對(duì)而言不大穩(wěn)定。是Linux 使用的擴(kuò)展了的DOS文件系統(tǒng)。它在 DOS 文件系統(tǒng)下增加了長(zhǎng)文件名、 UID/GID、POSIX 權(quán)限和特殊文件 (設(shè)備、命名管道等)功能,而不犧牲對(duì) DOS 的兼容性。允許一個(gè)普通的msdos文件系統(tǒng)用于Linux,而且無須為它建立單獨(dú)的分區(qū),特別適合早期的硬盤空間不足的硬件條件。
?
| VFS: Mounted root (romfs filesystem) readonly |
?
虛擬文件系統(tǒng)VFS(Virtual Filesystem Switch)的輸出信息。
再次強(qiáng)調(diào)一下一個(gè)概念。VFS 是一種軟件機(jī)制,也可稱它為 Linux 的文件系統(tǒng)管理者,它是用來管理實(shí)際文件系統(tǒng)的掛載點(diǎn),目的是為了能支持多種文件系統(tǒng)。kernel會(huì)先在內(nèi)存中建立一顆 VFS 目錄樹,是內(nèi)存中的一個(gè)數(shù)據(jù)對(duì)象,然后在其下掛載rootfs文件系統(tǒng),還可以掛載其他類型的文件系統(tǒng)到某個(gè)子目錄上。
?
| Mounted devfs on /dev |
?
加載devfs設(shè)備管理文件系統(tǒng)到dev安裝點(diǎn)上。
/dev是我們經(jīng)常會(huì)用到的一個(gè)目錄。
在2.4的kernel中才有使用到。每次啟動(dòng)時(shí)內(nèi)核會(huì)自動(dòng)掛載devfs。
devfs提供了訪問內(nèi)核設(shè)備的命名空間。它并不是建立或更改設(shè)備節(jié)點(diǎn),devfs只是為你的特別文件系統(tǒng)進(jìn)行維護(hù)。一般我們可以手工mknod創(chuàng)件設(shè)備節(jié)點(diǎn)。/dev目錄最初是空的,里面特定的文件是在系統(tǒng)啟動(dòng)時(shí)、或是加載模組后驅(qū)動(dòng)程序載入時(shí)建立的。當(dāng)模組和驅(qū)動(dòng)程序卸載時(shí),文件就消失了。
?
| Freeing init memory: 72K |
?
釋放1號(hào)用戶進(jìn)程init所占用的內(nèi)存。
?
第三節(jié):加載linux內(nèi)核完畢,轉(zhuǎn)入cpu_idle進(jìn)程
?
系統(tǒng)啟動(dòng)過程中進(jìn)程情況:
①init進(jìn)程
一般來說, 系統(tǒng)在跑完 kernel bootstrapping 內(nèi)核引導(dǎo)自舉后(被裝入內(nèi)存、已經(jīng)開始運(yùn)行、已經(jīng)初始化了所有的設(shè)備驅(qū)動(dòng)程序和數(shù)據(jù)結(jié)構(gòu)等等), 就去運(yùn)行 init『萬process之父』, 有了它, 才能開始跑其他的進(jìn)程,因此,init進(jìn)程,它是內(nèi)核啟動(dòng)的第一個(gè)用戶級(jí)進(jìn)程,它的進(jìn)程號(hào)總是1。
?
| 你可以用進(jìn)程查看命令來驗(yàn)證 # ps aux PID Uid VmSize Stat Command 1 0 SW init 2 0 SW [keventd] 3 0 SWN [ksoftirqd_CPU0] 4 0 SW [kswapd] 5 0 SW [bdflush] 6 0 SW [kupdated] 7 0 SW [rbwdg] 9 0 SW [mtdblockd] 10 0 SW [khubd] 80 0 SW [loop0] |
?
另外 Linux 有兩個(gè) kernel 類的 process 也開始跑了起來,一個(gè)是 kflushd/bdflush,另一個(gè)是 kswapd;
只有這個(gè) init 是完全屬于 user 類的進(jìn)程, 后兩者是 kernel假借 process 進(jìn)程之名掛在進(jìn)程上。
init有許多很重要的任務(wù),比如象啟動(dòng)getty(用于用戶登錄)、實(shí)現(xiàn)運(yùn)行級(jí)別、以及處理孤立進(jìn)程。
init 一開始就去讀 /etc/inittab (init初始化表),初始化表是按一定格式排列的關(guān)于進(jìn)程運(yùn)行時(shí)的有關(guān)信息的。init程序需要讀取/etc/inittab文件作為其行為指針。這個(gè) inittab 中對(duì)于各個(gè)runlevel運(yùn)行級(jí)別要跑哪些 rc 或 spawn 生出什么有很清楚的設(shè)定。
一般, 在Linux中初始化腳本在/etc/inittab 文件(或稱初始化表)中可以找到關(guān)于不同運(yùn)行級(jí)別的描述。inittab是以行為單位的描述性(非執(zhí)行性)文本,每一個(gè)指令行都是固定格式
inittab中有respawn項(xiàng),但如果一個(gè)命令運(yùn)行時(shí)失敗了,為了避免重運(yùn)行的頻率太高,init將追蹤一個(gè)命令重運(yùn)行了多少次,并且如果重運(yùn)行的頻率太高,它將被延時(shí)五分鐘后再運(yùn)行。
?
② kernel進(jìn)程
A> 請(qǐng)注意init是1號(hào)進(jìn)程,其他進(jìn)程id分別是kflushd/ bdflush, kupdate, kpiod and kswapd。這里有一個(gè)要指出的:你會(huì)注意到虛擬占用(SIZE)和實(shí)際占用(RSS)列都是0,進(jìn)程怎么會(huì)不使用內(nèi)存呢?
這些進(jìn)程就是內(nèi)核守護(hù)進(jìn)程。大部分內(nèi)核并不顯示在進(jìn)程列表里。守護(hù)進(jìn)程在init之后啟動(dòng),所以他們和其他進(jìn)程一樣有進(jìn)程ID,但是他們的代碼和數(shù)據(jù)都存放在內(nèi)核占有的內(nèi)存中。在列表中使用中括號(hào)來區(qū)別與其他進(jìn)程。
B> 輸入和輸出是通過內(nèi)存中的緩沖來完成的,這讓事情變得更快,程序的寫入會(huì)存放在內(nèi)存緩沖中,然后再一起寫入硬盤。守護(hù)進(jìn)程kflushd和kupdate 管理這些工作。kupdate間斷的工作(每5秒)來檢查是否有寫過的緩沖,如過有,就讓kflushd把它們寫入磁盤。
C> 進(jìn)程有時(shí)候無事可做,當(dāng)它運(yùn)行時(shí)也不一定需要把其所有的代碼和數(shù)據(jù)都放在內(nèi)存中。這就意味著我們可以通過把運(yùn)行中程序不用的內(nèi)容切換到交換分區(qū)來更好的是利用內(nèi)存。把這些進(jìn)程數(shù)據(jù)移入/移出內(nèi)存通過進(jìn)程IO管理守護(hù)進(jìn)程kpiod和交換守護(hù)進(jìn)程kswapd,大約每隔1秒,kswapd醒來并檢查內(nèi)存情況。如果在硬盤的東西要讀入內(nèi)存,或者內(nèi)存可用空間不足,kpiod就會(huì)被調(diào)用來做移入/移出操作。
D> bdflush - BUF_DIRTY, 將dirty緩存寫回到磁盤的核心守護(hù)進(jìn)程。 對(duì)于有許多臟的緩沖區(qū)(包含必須同時(shí)寫到磁盤的數(shù)據(jù)的緩沖區(qū))的系統(tǒng)提供了動(dòng)態(tài)的響應(yīng)。它在系統(tǒng)啟動(dòng)的時(shí)候作為一個(gè)核心線程啟動(dòng),它叫自己為“kflushd”,而這是你用ps顯示系統(tǒng)中的進(jìn)程的時(shí)候你會(huì)看得的名字。即定期(5秒)將臟(dirty)緩沖區(qū)的內(nèi)容寫入磁盤,以騰出內(nèi)存;
E> ksoftirqd_CPUx 是一個(gè)死循環(huán), 負(fù)責(zé)處理軟中斷的。它是用來對(duì)軟中斷隊(duì)列進(jìn)行緩沖處理的進(jìn)程。當(dāng)發(fā)生軟中斷時(shí),系統(tǒng)并不急于處理,只是將相應(yīng)的cpu的中斷狀態(tài)結(jié)構(gòu)中的active 的相應(yīng)的位,置位,并將相應(yīng)的處理函數(shù)掛到相應(yīng)的隊(duì)列,然后等待調(diào)度時(shí)機(jī)來臨,再來處理.
ksoftirqd_CPUx是由cpu_raise_softirq()即cpu觸發(fā)中斷,喚醒的內(nèi)核線程,這涉及到軟中斷,ksoftirqd的代碼參見 [kernel/softirq.c]
F> keventd,它的任務(wù)就是執(zhí)行 scheduler 調(diào)度器隊(duì)列中的任務(wù),keventd 為它運(yùn)行的任務(wù)提供了可預(yù)期的進(jìn)程上下文。
G> khubd, 是用來檢測(cè)USB hub設(shè)備的,當(dāng)usb有動(dòng)態(tài)插拔時(shí),將交由此內(nèi)核進(jìn)程來處理。在檢測(cè)到有hub事件時(shí)會(huì)有相應(yīng)的動(dòng)作(usb_hub_events())
H> mtdblockd是用來對(duì)flash塊設(shè)備進(jìn)行寫操作的守護(hù)進(jìn)程。
NAND類型的Flash需要MTD(Memory Technology Devices 內(nèi)存技術(shù)驅(qū)動(dòng)程序)驅(qū)動(dòng)的支持才能被linux所使用。
NAND的特點(diǎn)是不能在芯片內(nèi)執(zhí)行(XIP,eXecute In Place),需要把代碼讀到系統(tǒng)RAM中再執(zhí)行,傳輸效率不是最高,最大擦寫次數(shù)量為一百萬次,但寫入和擦除的速度很快,擦除單元小,是高數(shù)據(jù)存儲(chǔ)密度的最佳選擇。
NAND需要I/O接口,因此使用時(shí)需要驅(qū)動(dòng)程序。
I> loop0 是負(fù)責(zé)處理loop塊設(shè)備的(回環(huán)設(shè)備)。loopback device指的就是拿文件來模擬塊設(shè)備, 在我們這里,loop設(shè)備主要用來處理需要mount到板上的文件系統(tǒng),類似mount /tmp/rootfs /mnt -o loop。.我們的實(shí)例有:mount -o loop -t cramfs /xxx.bin /xxx 也就是將xxx.bin這個(gè)文件mount到板上來模擬cramfs壓縮ram文件系統(tǒng)。loop0進(jìn)程負(fù)責(zé)對(duì)loop設(shè)備進(jìn)行操作。
loopback設(shè)備和其他的塊設(shè)備的使用方法相同。特別的是,可以在該設(shè)備上建立一個(gè)文件系統(tǒng),然后利用mount命令把該系統(tǒng)映射到某個(gè)目錄下以便訪問。這種整個(gè)建立在一個(gè)普通磁盤文件上的文件系統(tǒng),就是虛擬文件系統(tǒng) (virtual file system)。
?
總結(jié):
上面的內(nèi)容是本人為了在實(shí)際開發(fā)中更加清楚地了解嵌入式linux的啟動(dòng)過程而做的一個(gè)總結(jié)性的文章。
在對(duì)嵌入式linux的啟動(dòng)過程做了一個(gè)詳細(xì)注釋后,大家會(huì)對(duì)涉及到嵌入系統(tǒng)的各個(gè)概念有了一個(gè)更加明確的認(rèn)識(shí),并能對(duì)嵌入系統(tǒng)的軟硬件環(huán)境的有關(guān)設(shè)置更加清楚。當(dāng)你自己動(dòng)手結(jié)合linux源代碼來分析時(shí),將會(huì)有一個(gè)清楚的全局觀。
現(xiàn)在,你如果再回頭去看文章前面所列出的啟動(dòng)信息例子中的內(nèi)容,其中80%的內(nèi)容,你現(xiàn)在應(yīng)該能看懂它的來龍去脈了。
總結(jié)
以上是生活随笔為你收集整理的嵌入式linux启动信息完全注释的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Word题注带一级标题,由图一.1变为图
- 下一篇: linux查询当前目录剩余空间,如何在l