uclinux表示micro-control linux.即“微控制器領(lǐng)域中的Linux系統(tǒng)”,是Lineo公司的主打產(chǎn)品,同時(shí)也是開放源碼的嵌入式Linux的典范之作。uCLinux主要是針對目標(biāo)處理器沒有存儲管理單元MMU(Memory Management Unit)的嵌入式系統(tǒng)而設(shè)計(jì)的。它已經(jīng)被成功地移植到了很多平臺上。由于沒有MMU,其多任務(wù)的實(shí)現(xiàn)需要一定技巧。
uClinux啟動過程
uCinux的啟動主要經(jīng)歷三個階段。首先,必須完成CPU和存儲器的硬件初始化,在系統(tǒng)RAM中建立程序堆棧和數(shù)據(jù)段,建立程序的運(yùn)行時(shí)的環(huán)境。初始化完成之后,uClinux內(nèi)核就取得了CPU的控制權(quán),開始操作系統(tǒng)自身的初始化,這包括建立RAM中斷矢量表、加載設(shè)備驅(qū)動程序、內(nèi)存管理模塊等等。這一切完成后,uClinux啟動一個最初的init線程,進(jìn)入到第三階段,這時(shí)內(nèi)核已經(jīng)正常運(yùn)行,外圍模塊也都就緒,開始執(zhí)行一些腳本文件(如/etc/rc腳本文件)。
一.kernel代碼段之前的系統(tǒng)初始化
1. uClinux-dist/linux-2.4.x/arch/armnommu/boot/compressed/head.S
開發(fā)板從上電開始,最開始執(zhí)行的程序放在uClinux-dist/linux-2.4.x/arch/armnommu/boot/compressed/head.S中。
(1) 切換模式,關(guān)閉中斷。 (line 96 )
(2) 首先程序要先給SYSCFG,EXTDBWTH,ROMCON0等一系列系統(tǒng)控制寄存器賦值,此時(shí)flash地址在 0X0,DRAM地址在0X1000000.(line 141 )
(3) 點(diǎn)亮I/O口的指示燈。 (line 152 )
(4) 把在flash上的image復(fù)制到DRAM上。(line 161 )
(5) 執(zhí)行remap,把flash地址映射為0X1000000,DRAM地址映射為0.(line 172 )
(6) 打開cache和write buffer.(line 196 )
(7) 設(shè)置好64K堆棧。(line 204 )
(8) 跳轉(zhuǎn)到decompress_kernel函數(shù)(line 217 ),此處的跳轉(zhuǎn)為帶返回的跳轉(zhuǎn),以便于執(zhí)行完此函數(shù)跳轉(zhuǎn)回來。
2. uClinux-dist/linux-2.4.x/arch/armnommu/boot/compressed/misc.c
此時(shí)的函數(shù)decompress_kernel是用C語言寫的,line 297 。
(1) makecrc();進(jìn)行crc校驗(yàn)。
(2) puts(“Uncompressing Linux.。.”); 輸出linux起動后的第一句話。
(3) gunzip();解壓縮kernel.
(4) puts(“ done, booting the kernel./n”);
3. uClinux-dist/linux-2.4.x/arch/armnommu/boot/compressed/head.S
執(zhí)行完decompress_kernel函數(shù)后,kernel又跳轉(zhuǎn)回head.S中,因?yàn)榇藭r(shí)我們還要檢驗(yàn)解壓縮之后的kernel起始地址是否緊接著kernel image,如果是,beq call_kernel(line 220),執(zhí)行解壓后的kernel.
如果解壓縮之后的kernel起始地址不是緊接著kernel image,執(zhí)行relocate(line 236),將其拷貝到緊接著kernel image的地方,然后跳轉(zhuǎn),執(zhí)行解壓后的kernel.
二.kernel執(zhí)行
1.uClinux-dist/linux-2.4.x/init/main.c中的start_kernel() (line 352)
系統(tǒng)啟動過程到此,轉(zhuǎn)入體系結(jié)構(gòu)無關(guān)的通用C代碼中,start_kernel() 中調(diào)用了一系列初始化函數(shù),以完成kernel本身的設(shè)置。這些動作有的是公共的,有的則是需要配置的才會執(zhí)行的。
(1) 輸出Linux版本信息(printk(linux_banner))
(2) 設(shè)置與體系結(jié)構(gòu)相關(guān)的環(huán)境(setup_arch())
(3) parse_options(command_line);解析command_line,將其轉(zhuǎn)化為環(huán)境變量。
(4) 初始化系統(tǒng)IRQ(init_IRQ())
(5) 核心進(jìn)程調(diào)度器初始化(sched_init())
(6) 軟中段初始化softirq_init();
(7) 時(shí)間、定時(shí)器初始化(包括估測主頻、初始化定時(shí)器中斷等,time_init())
(8) 控制臺初始化console_init();
(9) 核心CACHE初始化kmem_cache_init();
(10)延遲校準(zhǔn)calibrate_delay();
(11)內(nèi)存初始化(設(shè)置內(nèi)存上下界和頁表項(xiàng)初始值,mem_init())
(12)文件,目錄,塊設(shè)備讀寫緩沖區(qū)初始化
(13)檢查體系結(jié)構(gòu)漏洞(check_bugs())
(14)啟動init過程(創(chuàng)建第一個核心線程,調(diào)用init()函數(shù),原執(zhí)行序列調(diào)用cpu_idle() 等待調(diào)度,init())
至此start_kernel()結(jié)束,基本的核心環(huán)境已經(jīng)建立起來了。
2.uClinux-dist/linux-2.4.x/init/main.c中的init() (line 548)
現(xiàn)在我們進(jìn)入內(nèi)核引導(dǎo)第二部分,init()函數(shù)作為核心線程,首先鎖定內(nèi)核(僅對SMP機(jī)器有效,我們?yōu)榭蘸瘮?shù)),然后調(diào)用 do_basic_setup() (line 551)完成外設(shè)及其驅(qū)動程序的加載初始化。
過程如下:
* 網(wǎng)絡(luò)初始化(初始化網(wǎng)絡(luò)數(shù)據(jù)結(jié)構(gòu),包括sk_init()、skb_init()和proto_init()三部分,在proto_init()中,將調(diào)用protocols結(jié)構(gòu)中包含的所有協(xié)議的初始化過程,sock_init())
* 創(chuàng)建事件管理核心線程(start_context_thread()函數(shù),這是系統(tǒng)創(chuàng)建的第二個內(nèi)核線程,名叫“keventd”。其代碼context_thread()也在kernel/context.c中,)
啟動任何使用__initcall標(biāo)識的函數(shù)(方便核心開發(fā)者添加啟動函數(shù),此時(shí)由do_initcalls()函數(shù)啟動)。
此時(shí)系統(tǒng)開始加載外部設(shè)備的初始化程序,如:在linux-2.4.x/driver/block/genhd.c中的device_init()函數(shù),在genhd.c中由__initcall(device_init)標(biāo)識在此時(shí)調(diào)用,device_init()函數(shù)是所有外部設(shè)備初始化的總?cè)肟冢藟K設(shè)備的初始化blk_dev_init,網(wǎng)絡(luò)設(shè)備的初始化net_dev_init()和atmdev_init()等。
至此do_basic_setup()函數(shù)返回init(),在釋放啟動內(nèi)存段(free_initmem())并給內(nèi)核解鎖以后,init()打開/dev/console設(shè)備,重定向stdin、stdout和stderr到控制臺,最后,搜索文件系統(tǒng)中的init程序(或者由init=命令行參數(shù)指定的程序),并使用 execve()系統(tǒng)調(diào)用加載執(zhí)行init程序。(line 576) 。
init()函數(shù)到此結(jié)束,內(nèi)核的引導(dǎo)部分也到此結(jié)束了,
3. uClinux-dist/linux-2.4.x/init/main.c中的execve(“/etc/init”,argv_init,envp_init); (line 579)
init進(jìn)程是系統(tǒng)所有進(jìn)程的起點(diǎn),內(nèi)核在完成核內(nèi)引導(dǎo)以后,即在本線程(進(jìn)程)空間內(nèi)加載init程序,它的進(jìn)程號是1。
init程序需要讀取/vendors/SAMSUNG/4510B/inittab文件作為其行為指針,然后執(zhí)行。
4.系統(tǒng)執(zhí)行rc腳本。
hostname Samsung
/bin/expand /etc/ramfs.img /dev/ram0
/bin/expand /etc/ramfs2048.img /dev/ram1
mount -t proc proc /proc
mount -t ext2 /dev/ram0 /var
mount -t ext2 /dev/ram1 /ramdisk
chmod 777 /ramdisk
mkdir /var/config
mkdir /var/tmp
mkdir /var/log
mkdir /var/run
mkdir /var/lock
ifconfig lo 127.0.0.1
route add -net 127.0.0.0 netmask 255.255.255.0 lo
dhcpcd &
cat /etc/motd
rc程序執(zhí)行完畢后,系統(tǒng)環(huán)境已經(jīng)設(shè)置好了,下面就該用戶登錄系統(tǒng)了。
5.運(yùn)行Sash command shell
uclinux啟動的詳細(xì)過程有著諸多的信息可以給我們巨大的啟發(fā),我們在這里討論的就是要對這些信息做一個具體細(xì)致的分析,通過我們的討論,大家會對uclinux啟動過程中出現(xiàn)的、以前感覺熟悉的、但卻又似是而非的東西有一個確切的了解,并且能了解到這些輸出信息的來龍去脈。
uclinux的啟動過程,它是一幅縮影圖,對它有了一個詳細(xì)的了解后,有助于指導(dǎo)我們更加深入地了解uclinux的核心。
大家對uclinux的啟動應(yīng)該都比較熟悉,作為一名嵌入系統(tǒng)開發(fā)者,你一定遇到過下面的情景:在某論壇上看到一篇帖子,上面貼著uclinux開發(fā)板啟動時(shí)的一堆信息,然后大家在帖子里討論著這個啟動過程中出現(xiàn)的問題,隨機(jī)舉例如下:
Linux version 2.4.20-uc1 (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) 《mac@os.nctu.edu.tw》
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
評論
查看更多