新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 嵌入式linux啟動信息完全注釋

嵌入式linux啟動信息完全注釋

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

pid控制相關文章:pid控制原理


linux相關文章:linux教程


漏電開關相關文章:漏電開關原理


評論


相關推薦

技術專區(qū)

關閉