嵌入式linux啟動(dòng)信息完全注釋
作者: yut616@sohu.com 摘要 我們?cè)谶@里討論的是對(duì)嵌入式linux系統(tǒng)的啟動(dòng)過(guò)程的輸出信息的注釋,通過(guò)我們的討論,大家會(huì)對(duì)嵌入式linux啟動(dòng)過(guò)程中出現(xiàn)的、以前感覺(jué)熟悉的、但卻又似是而非的東西有一個(gè)確切的了解,并且能了解到這些輸出信息的來(lái)龍去脈。 嵌入式linux的啟動(dòng)信息是一個(gè)很值得我們?nèi)ズ煤醚芯康臇|西,它能將一幅縮影圖呈現(xiàn)在我們面前,來(lái)指導(dǎo)我們更加深入地理解linux內(nèi)核。 關(guān)鍵字:linux,嵌入式,啟動(dòng),bootloader 正文 作為一名嵌入系統(tǒng)開(kāi)發(fā)者,你一定遇到過(guò)下面的情景: 在某論壇上看到一篇帖子,上面貼著嵌入式linux開(kāi)發(fā)板啟動(dòng)時(shí)的有關(guān)信息,然后大家在帖子里討論著這個(gè)啟動(dòng)過(guò)程中出現(xiàn)的問(wèn)題,隨機(jī)舉例如下: Linux version 2.4.20-uc0 (root@Local) (gcc version 2.95.3 20010315 (release)(ColdFire patches - 20010318 from http://f (uClinux XIP and shared lib patches from http://www.snapgear.com/)) #20 三 6月 1 8 00:58:31 CST 2003 Processor: Samsung S3C4510B revision 6 Architecture: SNDS100 On node 0 totalpages: 4096 zone(0): 0 pages. zone(1): 4096 pages. zone(2): 0 pages. Kernel command line: root=/dev/rom0 Calibrating delay loop... 49.76 BogoMIPS Memory: 16MB = 16MB total Memory: 14348KB available (1615K code, 156K data, 40K init) Dentry cache hash table entries: 2048 (order: 2, 16384 bytes) Inode cache hash table entries: 1024 (order: 1, Mount-cache hash table entries: 512 (order: 0, 4096 bytes) Buffer-cache hash table entries: 1024 (order: 0, 4096 bytes) Page-cache hash table entries: 4096 (order: 2, 16384 bytes) POSIX conformance testing by UNIFIX Linux NET4.0 for Linux 2.4 Based upon Swansea University Computer Society NET3.039 Initializing RT netlink socket Starting kswapd Samsung S3C4510 Serial driver version 0.9 (2001-12-27) with no serial options en abled ttyS00 at 0x3ffd000 (irq = 5) is a S3C4510B ttyS01 at 0x3ffe000 (irq = 7) is a S3C451 Blkmem copyright 1998,1999 D. Jeff Dionne Blkmem copyright 1998 Kenneth Albanowski Blkmem 1 disk images: 0: BE558-1A5D57 [VIRTUAL BE558-1A5D57] (RO) RAMDISK driver initialized: 16 RAM disks of 1024K size 1024 blocksize Samsung S3C4510 Ethernet driver version 0.1 (2002-02-20) eth0: 00:40:95:36:35:34 NET4: Linux TCP/IP 1.0 for NET4.0 IP Protocols: ICMP, UDP, TCP IP: routing cache hash table of 512 buckets, 4Kbytes TCP: Hash tables configured (established 1024 bind 1024) VFS: Mounted root (romfs Freeing init memory: 40K 上面的這些輸出信息,也可能包括你自己正在做的嵌入式linux開(kāi)發(fā)板的輸出信息,其中的每一行,每一個(gè)字的含義,你是否深究過(guò),或者說(shuō)大部分的含義你能確切地知道的?本人想在這里結(jié)合本人在實(shí)踐中一些體會(huì)來(lái)和廣大嵌入式linux的開(kāi)發(fā)者一起讀懂這些信息。 我們?cè)谶@里將以一個(gè)真實(shí)的嵌入式linux系統(tǒng)的啟動(dòng)過(guò)程為例,來(lái)分析這些輸出信息。啟動(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 )開(kāi)始,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é)寫(xiě),每次可以傳輸8Bit。一般適合應(yīng)用于數(shù)據(jù)/程序的存貯應(yīng)用中.NOR還可以片內(nèi)執(zhí)行(execute-in-place)XIP.寫(xiě)入和擦除速度很低。 NAND Flash,1989年,東芝公司發(fā)明.是以塊和頁(yè)為單位來(lái)讀寫(xiě)的,不能隨機(jī)訪問(wèn)某個(gè)指定的點(diǎn).因而相對(duì)來(lái)說(shuō)讀取速度較慢,而擦除和寫(xiě)入的速度則比較快, 每次可以傳輸16Bit,一般適用在大容量的多媒體應(yīng)用中,容量大。如:CF,SM. ②串行Serial Flash 是以字節(jié)進(jìn)行傳輸?shù)模看慰梢詡鬏?-2Bit.如:MMC,SD,MS卡.串行閃存器件體積小,引腳也少,成本相對(duì)也更低廉。 ③不可擦除Mask Rom Flash的特點(diǎn)是一次性錄入數(shù)據(jù),具有不可更改性,經(jīng)常運(yùn)用于游戲和需版權(quán)保護(hù)文件等的錄入。其顯著特點(diǎn)是成本低。 注意:任何flash器件的寫(xiě)入操作只能在空或已擦除的單元內(nèi)進(jìn)行,所以大多數(shù)情況下,在進(jìn)行寫(xiě)入操作之前必須先執(zhí)行擦除。NAND器件執(zhí)行擦除操作是十分簡(jiǎn)單的,而NOR則要求在進(jìn)行擦除前先要將目標(biāo)塊內(nèi)所有的位都寫(xiě)為0。 從上面的信息,我們可以對(duì)flash類型特點(diǎn)有個(gè)比較明確的了解。 CPU clock rate: 200 MHz 開(kāi)發(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沒(méi)有刷新周期。每個(gè)SRAM存儲(chǔ)單元由6個(gè)晶體管組成,而DRAM存儲(chǔ)單元由一個(gè)晶體管和一個(gè)電容器組成。相比而言,DRAM比SRAM每個(gè)存儲(chǔ)單元的成本要高。照此推理,可以斷定在給定的固定區(qū)域內(nèi)DRAM的密度比SRAM 的密度要大。 SRAM常常用于高速緩沖存儲(chǔ)器,因?yàn)樗懈叩乃俾?而DRAM常常用于PC中的主存儲(chǔ)器,因?yàn)槠鋼碛懈叩拿芏取? 在嵌入式系統(tǒng)中使用DRAM內(nèi)存的設(shè)計(jì)比較廣泛。 地址輔助說(shuō)明: 先說(shuō)明一下內(nèi)存地址數(shù)字情況,主要是為了方便記憶。 可以訪問(wèn)的內(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ù)來(lái)快速知道換算后的地址是在多少兆的地方。比如,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ū)域來(lái)分別存放。 VFS虛擬文件系統(tǒng)交換器 在linux系統(tǒng)中,目前已經(jīng)開(kāi)發(fā)出多種文件系統(tǒng),那么如何讓這些文件系統(tǒng)能共存在一個(gè)系統(tǒng)中呢,從linux 2.0開(kāi)始,引入了虛擬文件系統(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 的目錄樹(shù)。VFS 中的各目錄其主要用途是用來(lái)提供實(shí)際文件系統(tǒng)的掛載點(diǎn)。而rootfs將是這個(gè)目錄樹(shù)的根結(jié)點(diǎn)的(root),即 "/"目錄,VFS的結(jié)構(gòu)就是從這個(gè)rootfs開(kāi)始的。有了VFS,那么對(duì)文件的操作將使用統(tǒng)一的接口,將來(lái)通過(guò)文件系統(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),是為了保持制作出來(lái)的整個(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)過(guò)程了。 第二部分 : 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ù),來(lái)完成內(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ì)打印一下的信息,如果你沒(méi)有把這句去掉的話。 Found bootloader memory map at 0x10000fc0. bootloader經(jīng)過(guò)內(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(在后面的說(shuō)明中會(huì)看到mtdblock3是指的flash上的romfs分區(qū)。),用來(lái)指定根文件系統(tǒng)所在的位置,kernel會(huì)將塊設(shè)備mtdblock3當(dāng)作文件系統(tǒng)來(lái)處理。 也就是說(shuō),內(nèi)核會(huì)根據(jù)上面的kernel命令行,知道只讀文件系統(tǒng)romfs將是根文件系統(tǒng)rootfs。 start_kernel(void)中輸出的上面的這句信息。 這行命令是在linux內(nèi)核啟動(dòng)過(guò)程中都會(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(每秒百萬(wàn)條指令),Bogo是Bogus(偽)的意思。這里是對(duì)CPU進(jìn)行一個(gè)實(shí)時(shí)測(cè)試,來(lái)得到一個(gè)大體的 MIPS數(shù)值 Bogomips,是由linus Torvalds寫(xiě)的, 是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ì)算出來(lái)的值經(jīng)過(guò)處理后得到 BogoMIPS值 你可以將計(jì)算機(jī)的bogomips與計(jì)算機(jī)處理器的bogomips進(jìn)行比較。Torvalds稱這個(gè)程序?yàn)锽ogoMips來(lái)暗示兩臺(tái)計(jì)算機(jī)間的性能度量是錯(cuò)誤的,因?yàn)椴⒎撬衅鹱饔靡蛩囟寄鼙伙@示出來(lái)或被認(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ì)打印出來(lái)。 進(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,用來(lái)在內(nèi)存與磁盤間做緩沖處理; Page Cache 用來(lái)加快對(duì)磁盤上映像和數(shù)據(jù)的訪問(wèn)。 在內(nèi)存中建立各個(gè)緩沖hash表,為kernel對(duì)文件系統(tǒng)的訪問(wèn)做準(zhǔn)備。 VFS(virtual filesystem switch)虛擬文件切換目錄樹(shù)有用到類似這樣的結(jié)構(gòu)表。 上面的輸出信息,在一般的linux啟動(dòng)過(guò)程中都會(huì)看到。 POSIX conformance testing by UNIFIX conformance:順應(yīng), 一致。即POSIX適應(yīng)性檢測(cè)。UNIFIX是一家德國(guó)的技術(shù)公司,Linux 原本要基于 POSIX.1 的, 但是 POSIX 不是免費(fèi)的, 而且 POSIX.1 證書(shū)相當(dāng)昂貴. 這使得 Linux 基于 POSIX 開(kāi)發(fā)相當(dāng)困難. Unifix公司(Braunschweig, 德國(guó)) 開(kāi)發(fā)了一個(gè)獲得了 FIPS 151-2 證書(shū)的 Linux 系統(tǒng). 這種技術(shù)用于 Unifix 的發(fā)行版 Unifix Linux 2.0 和 Lasermoon 的 Linux-FT。 在2.6的內(nèi)核中就將上面的這句輸出給拿掉了。 第二節(jié):用戶模式( user_mode )開(kāi)始,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)過(guò)程中都會(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)過(guò)程中都會(huì)出現(xiàn)。 Starting kswapd 啟動(dòng)交換守護(hù)進(jìn)程kswapd,進(jìn)程IO操作例程kpiod kswapd可以配合kpiod運(yùn)行。進(jìn)程有時(shí)候無(wú)事可做,當(dāng)它運(yùn)行時(shí)也不一定需要把其所有的代碼和數(shù)據(jù)都放在內(nèi)存中。這就意味著我們可以通過(guò)把運(yùn)行中程序不用的內(nèi)容切換到交換分區(qū)來(lái)更好的是利用內(nèi)存。大約每隔1秒,kswapd醒來(lái)并檢查內(nèi)存情況。如果在硬盤的東西要讀入內(nèi)存,或者內(nèi)存可用空間不足,kpiod就會(huì)被調(diào)用來(lái)做移入/移出操作。kswapd負(fù)責(zé)檢查,kpiod負(fù)責(zé)移動(dòng)。 Journalled Block Device driver loaded 加載日志塊設(shè)備驅(qū)動(dòng)。 日志塊設(shè)備是用來(lái)對(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ū)中保存有日志記錄,寫(xiě)操作首先是對(duì)記錄文件進(jìn)行操作,若整個(gè)寫(xiě)操作由于某種原因(如系統(tǒng)掉電)而中斷,系統(tǒng)重啟時(shí),會(huì)根據(jù)日志記錄來(lái)恢復(fù)中斷前的寫(xiě)操作。在日志文件系統(tǒng)中,所有的文件系統(tǒng)的變化都被記錄到日志,每隔一定時(shí)間,文件系統(tǒng)會(huì)將更新后的元數(shù)據(jù)及文件內(nèi)容寫(xiě)入磁盤。在對(duì)元數(shù)據(jù)做任何改變以前,文件系統(tǒng)驅(qū)動(dòng)程序會(huì)向日志中寫(xiě)入一個(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è)置。 將通過(guò) devpts 文件系統(tǒng)使用 Unix98 PTYs,(Pseudo-ttys (telnet etc) device是偽ttys設(shè)備的縮寫(xiě)。 ① TTY(/dev/tty)是TeleTYpe的一個(gè)老縮寫(xiě),為用戶輸入提供不同控制臺(tái)的設(shè)備驅(qū)動(dòng)程序。它的名字來(lái)源于實(shí)際掛接到 UNIX系統(tǒng)的、被稱為電傳打字機(jī)(teletype)的終端。在Linux下,這些文件提供對(duì)虛擬控制臺(tái)的支持,可以通過(guò)按到鍵來(lái)訪問(wèn)這些虛擬控制臺(tái)。這些虛擬控制臺(tái)提供獨(dú)立的、同時(shí)進(jìn)行的本地登錄對(duì)話過(guò)程 ② ttys(/dev/ttys)是計(jì)算機(jī)終端的串行接口。/dev/ttyS0對(duì)應(yīng)MS-DOS下的 COM1。 使用 make dev腳本MAKEDEV來(lái)建立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來(lái)實(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ù)包的開(kāi)始地址+第一個(gè)數(shù)據(jù)包的長(zhǎng)度)。設(shè)備會(huì)一直保留緩沖區(qū)內(nèi)的數(shù)據(jù)直到整個(gè)緩沖區(qū)耗盡。這樣,設(shè)備會(huì)再次重寫(xiě)緩沖區(qū)內(nèi)起始位置的內(nèi)容,就像一個(gè)環(huán)那樣。 從 2.2 版內(nèi)核升級(jí)到 2.4 版時(shí), RTL-8139 支持模塊已不再叫 rtl8139,而叫它 8139too,現(xiàn)在你再看到8139too就不會(huì)不明白它的來(lái)由了吧。 SCSI subsystem driver Revision: 1.00 USB設(shè)備信息,USB會(huì)被當(dāng)做SCSI來(lái)處理。 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,在我們開(kāi)發(fā)中會(huì)經(jīng)??吹?。以后大家看到Spansion的芯片,就能了解到它和AMD還有富士通的來(lái)龍去脈了。 Common flash Interface (CFI)是指一個(gè)統(tǒng)一的flash訪問(wèn)接口,表示這種flash是這種接口類型的。 Using buffer write method 使用flash寫(xiě)緩沖方式 flash提供了寫(xiě)B(tài)UFFER的命令來(lái)加快對(duì)flash上塊的操作。對(duì)Flash擦除和寫(xiě)數(shù)據(jù)是很慢的。如果用寫(xiě)B(tài)UFFER的命令會(huì)快一點(diǎn)。據(jù)手冊(cè)上說(shuō),會(huì)快20倍。Buffer Size :5 bytes的buffer緩沖不是每個(gè)塊都有,是整個(gè)flash只有一個(gè)5 bytes的buffer,用寫(xiě)B(tài)UFFER命令對(duì)所有的塊進(jìn)行寫(xiě)操作,都要用同一個(gè)buffer,寫(xiě)B(tài)uffer是主要檢查buffer是否 available,其實(shí)buffer起緩沖作用,來(lái)提高工作效率。 比如某flash有128個(gè)128K字節(jié)塊。允許用戶對(duì)任意塊進(jìn)行字節(jié)編程和寫(xiě)緩沖器字節(jié)編程操作,每字節(jié)編程時(shí)間為210μs;若采用寫(xiě)緩沖器字節(jié)編程方式,32字節(jié)編程共需218μs,每字節(jié)編程時(shí)間僅為6.8μs。芯片的塊擦除時(shí)間為1s,允許在編程或塊擦除操作的同時(shí)進(jìn)行懸掛中斷去進(jìn)行讀操作,待讀操作完成后,寫(xiě)入懸掛恢復(fù)命令,再繼續(xù)編程或塊擦除。 Creating 3 MTD partitions on "XX mapped flash": 0x00000000-0x00020000 : "BootLoader" 0x00020000-0x00040000 : "Config" 0x00040000-0x01000000 : "Romfs" 此處為重要信息部分,需要特別留意。 在內(nèi)存中映射過(guò)的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 開(kāi)發(fā)的一種塊設(shè)備驅(qū)動(dòng),它是嵌入式linux系統(tǒng)中最為古老和通用的塊設(shè)備驅(qū)動(dòng)。它原理相對(duì)簡(jiǎn)單但是配置比較復(fù)雜,需要根據(jù)你即的Flash的分區(qū)使用情況來(lái)修改代碼。當(dāng)然修改的結(jié)果是它可以對(duì)一些NOR型的Flash進(jìn)行讀寫(xiě)操作。不過(guò)目前支持的Flash類型不夠多。如果新加入對(duì)一種Flash的支持需要作的工作量比較大。 Linux的MTD驅(qū)動(dòng)是標(biāo)準(zhǔn)Linux的Flash驅(qū)動(dòng)。它支持大量的設(shè)備,有足夠的功能來(lái)定義Flash的分區(qū),進(jìn)行地址映射等等。使用MTD你可以在一個(gè)系統(tǒng)中使用不同類型的Flash。它可以將不同的Flash組合成一個(gè)線性的地址讓你來(lái)使用。 在標(biāo)準(zhǔn)的Linux 2.4內(nèi)核中MTD有一系列的選項(xiàng),你可以根據(jù)個(gè)人系統(tǒng)的需要來(lái)選擇,定制。 另外一種選擇就是RAM disk 驅(qū)動(dòng)。在PC上它經(jīng)常用于沒(méi)有硬盤的Linux的啟動(dòng)過(guò)程。它和Flash沒(méi)有直接的關(guān)系。不過(guò)當(dāng)Flash上啟動(dòng)的是經(jīng)過(guò)壓縮的內(nèi)核時(shí)。RAM disk 可以作為根文件系統(tǒng)。 MTD 驅(qū)動(dòng)提供了對(duì)Flash強(qiáng)大的支持,你通過(guò)它甚至可以在Flash上運(yùn)行一個(gè)可以讀寫(xiě)的真正的文件系統(tǒng),比如JFFS2。而B(niǎo)lkmem驅(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)過(guò)程中被socket.c調(diào)用到。 IP Protocols: ICMP, UDP, TCP, IGMP 列出可以支持的IP協(xié)議,此處為kernel源代碼inet_add_protocol(p);的輸出。 在linux啟動(dòng)過(guò)程中,都會(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)心這沒(méi)有什么害處,這個(gè)是kernel的書(shū)寫(xiě)bug,在2.6中有修改之,它是一個(gè)警告信息,用來(lái)檢查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(%26;amp;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ù)寫(xiě)到了文件系統(tǒng)的超級(jí)塊分區(qū)中),那么系統(tǒng)可能會(huì)完全不識(shí)別該文件系統(tǒng),這樣也就不能安裝它了,即使采用e2fsck 命令也不能處理這個(gè)問(wèn)題。 Cramfs文件系統(tǒng): cramfs 是 Linus Torvalds 本人開(kāi)發(fā)的一個(gè)適用于嵌入式系統(tǒng)的小文件系統(tǒng)。由于它是只讀的,所以,雖然它采取了 zlib 做壓縮,但是它還是可以做到高效的隨機(jī)讀取。 cramfs 不會(huì)影響系統(tǒng)讀取文件的速度,又是一個(gè)高度壓縮的文件系統(tǒng)。 我們制作image文件之后,我們還要考慮怎樣才能在系統(tǒng)運(yùn)行的時(shí)候,把這個(gè) image 文件 mount 上來(lái),成為一個(gè)可用的文件系統(tǒng)。由于這個(gè) image 文件不是一個(gè)通常意義上的 block 設(shè)備,我們必須采用 loopback 設(shè)備來(lái)完成這一任務(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通過(guò)優(yōu)化索引節(jié)點(diǎn)表的尺寸和除去傳統(tǒng)文件系統(tǒng)中文件之間的空間浪費(fèi)來(lái)達(dá)到節(jié)約空間的目的。它還使用了zlib壓縮,實(shí)現(xiàn)優(yōu)于2:1的壓縮比例。解壓縮過(guò)程的系統(tǒng)開(kāi)銷并不是很大,因?yàn)镃ramfs支持指定單塊的解壓,而并不必解壓縮整個(gè)文件。 Cramfs不僅能節(jié)省空間,還能避免非正常關(guān)機(jī)導(dǎo)致的等待fsck或手工進(jìn)行fsck的麻煩。它通過(guò)只讀的方式達(dá)到這一目的。 RamDisk有三種實(shí)現(xiàn)方式: 在Linux中可以將一部分內(nèi)存mount為分區(qū)來(lái)使用,通常稱之為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才支持的,通過(guò)Ramfs或者Tmpfs來(lái)實(shí)現(xiàn): 它們不需經(jīng)過(guò)格式化,用起來(lái)靈活,其大小隨所需要的空間而增加或減少。 Ramfs顧名思義是內(nèi)存文件系統(tǒng),它處于虛擬文件系統(tǒng)(VFS)層,而不像ramdisk那樣基于虛擬在內(nèi)存中的其他文件系統(tǒng)(ex2fs)。 因而,它無(wú)需格式化,可以創(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)存大小的一半??梢酝ㄟ^(guò)maxsize(以kbyte為單位)選項(xiàng)來(lái)改變。 # mount -t ramfs none /testRAM -o maxsize=2000 (創(chuàng)建了一個(gè)限定最大使用內(nèi)存為2M的ramdisk) ③ Tmpfs是一個(gè)虛擬內(nèi)存文件系統(tǒng),它不同于傳統(tǒng)的用塊設(shè)備形式來(lái)實(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)來(lái)負(fù)責(zé)分配和管理。 Tmpfs向虛擬內(nèi)存子系統(tǒng)請(qǐng)求頁(yè)來(lái)存儲(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,而且無(wú)須為它建立單獨(dú)的分區(qū),特別適合早期的硬盤空間不足的硬件條件。 VFS: Mounted root (romfs filesystem) readonly 虛擬文件系統(tǒng)VFS(Virtual Filesystem Switch)的輸出信息。 再次強(qiáng)調(diào)一下一個(gè)概念。VFS 是一種軟件機(jī)制,也可稱它為 Linux 的文件系統(tǒng)管理者,它是用來(lái)管理實(shí)際文件系統(tǒng)的掛載點(diǎn),目的是為了能支持多種文件系統(tǒng)。kernel會(huì)先在內(nèi)存中建立一顆 VFS 目錄樹(shù),是內(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提供了訪問(wèn)內(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)過(guò)程中進(jìn)程情況: ①init進(jìn)程 一般來(lái)說(shuō), 系統(tǒng)在跑完 kernel bootstrapping 內(nèi)核引導(dǎo)自舉后(被裝入內(nèi)存、已經(jīng)開(kāi)始運(yùn)行、已經(jīng)初始化了所有的設(shè)備驅(qū)動(dòng)程序和數(shù)據(jù)結(jié)構(gòu)等等), 就去運(yùn)行 init『萬(wàn)process之父』, 有了它, 才能開(kāi)始跑其他的進(jìn)程,因此,init進(jìn)程,它是內(nèi)核啟動(dòng)的第一個(gè)用戶級(jí)進(jìn)程,它的進(jìn)程號(hào)總是1。 你可以用進(jìn)程查看命令來(lái)驗(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 也開(kāi)始跑了起來(lái),一個(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 一開(kāi)始就去讀 /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)來(lái)區(qū)別與其他進(jìn)程。 B> 輸入和輸出是通過(guò)內(nèi)存中的緩沖來(lái)完成的,這讓事情變得更快,程序的寫(xiě)入會(huì)存放在內(nèi)存緩沖中,然后再一起寫(xiě)入硬盤。守護(hù)進(jìn)程kflushd和kupdate 管理這些工作。kupdate間斷的工作(每5秒)來(lái)檢查是否有寫(xiě)過(guò)的緩沖,如過(guò)有,就讓kflushd把它們寫(xiě)入磁盤。 C> 進(jìn)程有時(shí)候無(wú)事可做,當(dāng)它運(yùn)行時(shí)也不一定需要把其所有的代碼和數(shù)據(jù)都放在內(nèi)存中。這就意味著我們可以通過(guò)把運(yùn)行中程序不用的內(nèi)容切換到交換分區(qū)來(lái)更好的是利用內(nèi)存。把這些進(jìn)程數(shù)據(jù)移入/移出內(nèi)存通過(guò)進(jìn)程IO管理守護(hù)進(jìn)程kpiod和交換守護(hù)進(jìn)程kswapd,大約每隔1秒,kswapd醒來(lái)并檢查內(nèi)存情況。如果在硬盤的東西要讀入內(nèi)存,或者內(nèi)存可用空間不足,kpiod就會(huì)被調(diào)用來(lái)做移入/移出操作。 D> bdflush - BUF_DIRTY, 將dirty緩存寫(xiě)回到磁盤的核心守護(hù)進(jìn)程。 對(duì)于有許多臟的緩沖區(qū)(包含必須同時(shí)寫(xiě)到磁盤的數(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)容寫(xiě)入磁盤,以騰出內(nèi)存; E> ksoftirqd_CPUx 是一個(gè)死循環(huán), 負(fù)責(zé)處理軟中斷的。它是用來(lái)對(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ī)來(lái)臨,再來(lái)處理. ksoftirqd_CPUx是由cpu_raise_softirq()即cpu觸發(fā)中斷,喚醒的內(nèi)核線程,這涉及到軟中斷,ksoftirqd的代碼參見(jiàn) [kernel/softirq.c] F> keventd,它的任務(wù)就是執(zhí)行 scheduler 調(diào)度器隊(duì)列中的任務(wù),keventd 為它運(yùn)行的任務(wù)提供了可預(yù)期的進(jìn)程上下文。 G> khubd, 是用來(lái)檢測(cè)USB hub設(shè)備的,當(dāng)usb有動(dòng)態(tài)插拔時(shí),將交由此內(nèi)核進(jìn)程來(lái)處理。在檢測(cè)到有hub事件時(shí)會(huì)有相應(yīng)的動(dòng)作(usb_hub_events()) H> mtdblockd是用來(lái)對(duì)flash塊設(shè)備進(jìn)行寫(xiě)操作的守護(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í)行,傳輸效率不是最高,最大擦寫(xiě)次數(shù)量為一百萬(wàn)次,但寫(xiě)入和擦除的速度很快,擦除單元小,是高數(shù)據(jù)存儲(chǔ)密度的最佳選擇。 NAND需要I/O接口,因此使用時(shí)需要驅(qū)動(dòng)程序。 I> loop0 是負(fù)責(zé)處理loop塊設(shè)備的(回環(huán)設(shè)備)。loopback device指的就是拿文件來(lái)模擬塊設(shè)備, 在我們這里,loop設(shè)備主要用來(lái)處理需要mount到板上的文件系統(tǒng),類似mount /tmp/rootfs /mnt -o loop。.我們的實(shí)例有:mount -o loop -t cramfs /xxx.bin /xxx 也就是將xxx.bin這個(gè)文件mount到板上來(lái)模擬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è)目錄下以便訪問(wèn)。這種整個(gè)建立在一個(gè)普通磁盤文件上的文件系統(tǒng),就是虛擬文件系統(tǒng) (virtual file system)。 總結(jié): 上面的內(nèi)容是本人為了在實(shí)際開(kāi)發(fā)中更加清楚地了解嵌入式linux的啟動(dòng)過(guò)程而做的一個(gè)總結(jié)性的文章。 在對(duì)嵌入式linux的啟動(dòng)過(guò)程做了一個(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源代碼來(lái)分析時(shí),將會(huì)有一個(gè)清楚的全局觀。 現(xiàn)在,你如果再回頭去看文章前面所列出的啟動(dòng)信息例子中的內(nèi)容,其中80%的內(nèi)容,你現(xiàn)在應(yīng)該能看懂它的來(lái)龍去脈了。[!--empirenews.page--]