關(guān)于uclinux系統分析
簡(jiǎn)介
本文引用地址:http://dyxdggzs.com/article/148508.htmLinux是一種很受歡迎的操作系統,它與Unix系統兼容,開(kāi)放源代碼。它原本被設計為桌面系統,現在廣泛應用于服務(wù)器領(lǐng)域。而更大的影響在于它正逐漸的應用于嵌入式設備。uClinux正是在這種氛圍下產(chǎn)生的。在uClinux這個(gè)英文單詞中u表示Micro,小的意思,C表示Control,控制的意思,所以uClinux就是Micro-CONtrol-Linux,字面上的理解就是針對微控制領(lǐng)域而設計的Linux系統。
uClinux小型化的做法
標準Linux可能采用的小型化方法:
1、重新編譯內核
Linux內核采用模塊化的設計,即很多功能塊可以獨立的加上或卸下,開(kāi)發(fā)人員在設計內核時(shí)把這些內核模塊作為可選的選項,可以在編譯系統內核時(shí)指定。因此一種較通用的做法是對Linux內核重新編譯,在編譯時(shí)仔細的選擇嵌入式設備所需要的功能支持模塊,同時(shí)刪除不需要的功能。通過(guò)對內核的重新配置,可以使系統運行所需要的內核顯著(zhù)減小,從而縮減資源使用量。
2、制作root文件系統映象
Linux系統在啟動(dòng)時(shí)必須加載根(root)文件系統,因此剪裁系統同時(shí)包括root file system的剪裁。在x86系統下,Linux可以在Dos下,使用Loadlin文件加載啟動(dòng)。
uClinux采用的小型化方法:
1、uClinux的內核加載方式
uClinux的內核有兩種可選的運行方式:可以在flash上直接運行,也可以加載到內存中運行。這種做法可以減少內存需要。
Flash運行方式:把內核的可執行映象燒寫(xiě)到flash上,系統啟動(dòng)時(shí)從flash的某個(gè)地址開(kāi)始逐句執行。這種方法實(shí)際上是很多嵌入式系統采用的方法。
內核加載方式:把內核的壓縮文件存放在flash上,系統啟動(dòng)時(shí)讀取壓縮文件在內存里解壓,然后開(kāi)始執行,這種方式相對復雜一些,但是運行速度可能更快(ram的存取速率要比f(wàn)lash高)。同時(shí)這也是標準Linux系統采用的啟動(dòng)方式。
2、uClinux的根(root)文件系統
uClinux系統采用romfs文件系統,這種文件系統相對于一般的ext2文件系統要求更少的空間??臻g的節約來(lái)自于兩個(gè)方面,首先內核支持romfs文件系統比支持ext2文件系統需要更少的代碼,其次romfs文件系統相對簡(jiǎn)單,在建立文件系統超級塊(superblock)需要更少的存儲空間。Romfs文件系統不支持動(dòng)態(tài)擦寫(xiě)保存,對于系統需要動(dòng)態(tài)保存的數據采用虛擬ram盤(pán)的方法進(jìn)行處理(ram盤(pán)將采用ext2文件系統)。
3、uClinux的應用程序庫
uClinux小型化的另一個(gè)做法是重寫(xiě)了應用程序庫,相對于越來(lái)越大且越來(lái)越全的glibc庫,uClibc對libc做了精簡(jiǎn)。
uClinux對用戶(hù)程序采用靜態(tài)連接的形式,這種做法會(huì )使應用程序變大,但是基于內存管理的問(wèn)題,不得不這樣做(這將在下文對uClinux內存管理展開(kāi)分析時(shí)進(jìn)行說(shuō)明),同時(shí)這種做法也更接近于通常嵌入式系統的做法。
uClinux的開(kāi)發(fā)環(huán)境
GNU開(kāi)發(fā)套件
Gnu開(kāi)發(fā)套件作為通用的Linux開(kāi)放套件,包括一系列的開(kāi)發(fā)調試工具。主要組件:
Gcc: 編譯器,可以做成交叉編譯的形式,即在宿主機上開(kāi)發(fā)編譯目標上可運行的二進(jìn)制文件。
Binutils:一些輔助工具,包括 objdump(可以反編譯二進(jìn)制文件),as(匯編編譯器),ld(連接器)等等。
Gdb:調試器,可使用多種交叉調試方式,gdb-bdm (背景調試工具),gdbserver(使用以太網(wǎng)絡(luò )調試)。
uClinux的打印終端
通常情況下,uClinux的默認終端是串口,內核在啟動(dòng)時(shí)所有的信息都打印到串口終端(使用printk函數打印),同時(shí)也可以通過(guò)串口終端與系統交互?! Clinux在啟動(dòng)時(shí)啟動(dòng)了telnetd(遠程登錄服務(wù)),操作者可以遠程登錄上系統,從而控制系統的運行。至于是否允許遠程登錄可以通過(guò)燒寫(xiě)romfs文件系統時(shí)有用戶(hù)決定是否啟動(dòng)遠程登錄服務(wù)。
交叉編譯調試工具
支持一種新的處理器,必須具備一些編譯,匯編工具,使用這些工具可以形成可運行于這種處理器的二進(jìn)制文件。對于內核使用的編譯工具同應用程序使用的有所不同。在解釋不同點(diǎn)之前,需要對gcc連接做一些說(shuō)明:
.ld(link description)文件:ld文件是指出連接時(shí)內存映象格式的文件。
crt0.S:應用程序編譯連接時(shí)需要的啟動(dòng)文件,主要是初始化應用程序棧。
pic:position independence code ,與位置無(wú)關(guān)的二進(jìn)制格式文件,在程序段中必須包括reloc段,從而使的代碼加載時(shí)可以進(jìn)行重新定位。
內核編譯連接時(shí),使用ucsimm.ld文件,形成可執行文件映象,所形成的代碼段既可以使用間接尋址方式(即使用reloc段進(jìn)行尋址),也可以使用絕對尋址方式。這樣可以給編譯器更多的優(yōu)化空間。因為內核可能使用絕對尋址,所以?xún)群思虞d到的內存地址空間必須與ld文件中給定的內存空間完全相同。
應用程序的連接與內核連接方式不同。應用程序由內核加載(可執行文件加載器將在后面討論),由于應用程序的ld文件給出的內存空間與應用程序實(shí)際被加載的內存位置可能不同,這樣在應用程序加載的過(guò)程中需要一個(gè)重新地位的過(guò)程,即對reloc段進(jìn)行修正,使得程序進(jìn)行間接尋址時(shí)不至于出錯。(這個(gè)問(wèn)題在i386等高級處理器上方法有所不同,本文將在后面進(jìn)一步分析)。
由上述討論,至少需要兩套編譯連接工具。在討論過(guò)uClinux的內存管理后本文將給出整個(gè)系統的工作流程以及系統在flash和ram中的空間分布。
可執行文件格式
先對一些名詞作一些說(shuō)明:
coff(common object file format):一種通用的對象文件格式
elf(excutive linked file):一種為L(cháng)inux系統所采用的通用文件格式,支持動(dòng)態(tài)連接
flat:elf格式有很大的文件頭,flat文件對文件頭和一些段信息做了簡(jiǎn)化
uClinux系統使用flat可執行文件格式,gcc的編譯器不能直接形成這種文件格式,但是可以形成coff或elf格式的可執行文件,這兩種文件需要coff2flt或elf2flt工具進(jìn)行格式轉化,形成flat文件。
當用戶(hù)執行一個(gè)應用時(shí),內核的執行文件加載器將對flat文件進(jìn)行進(jìn)一步處理,主要是對reloc段進(jìn)行修正(可執行文件加載器的詳見(jiàn)fs/binfmt_flat.c)。以下對reloc段進(jìn)一步討論。
需要reloc段的根本原因是,程序在連接時(shí)連接器所假定的程序運行空間與實(shí)際程序加載到的內存空間不同。假如有這樣一條指令: jsr app_STart;
這一條指令采用直接尋址,跳轉到app_start地址處執行,連接程序將在編譯完成是計算出app_start的實(shí)際地址(設若實(shí)際地址為0x10000),這個(gè)實(shí)際地址是根據ld文件計算出來(lái)(因為連接器假定該程序將被加載到由ld文件指明的內存空間)。但實(shí)際上由于內存分配的關(guān)系,操作系統在加載時(shí)無(wú)法保證程序將按ld文件加載。這時(shí)如果程序仍然跳轉到絕對地址0x10000處執行,通常情況這是不正確的。一個(gè)解決辦法是增加一個(gè)存儲空間,用于存儲app_start的實(shí)際地址,設若使用變量addr表示這個(gè)存儲空間。則以上這句程序將改為:
movl addr, a0;
jsr (a0);
增加的變量addr將在數據段中占用一個(gè)4字節的空間,連接器將app_start的絕對地址存儲到該變量。在可執行文件加載時(shí),可執行文件加載器根據程序將要加載的內存空間計算出app_start在內存中的實(shí)際位置,寫(xiě)入addr變量。系統在實(shí)際處理是不需要知道這個(gè)變量的確切存儲位置(也不可能知道),系統只要對整個(gè)reloc段進(jìn)行處理就可以了(reloc段有標識,系統可以讀出來(lái))。處理很簡(jiǎn)單只需要對reloc段中存儲的值統一加上一個(gè)偏置(如果加載的空間比預想的要靠前,實(shí)際上是減去一個(gè)偏移量)。偏置由實(shí)際的物理地址起始值同ld文件指定的地址起始值相減計算出。
這種reloc的方式部分是由uClinux的內存分配問(wèn)題引起的,這一點(diǎn)將在uClinux內存管理分析時(shí)說(shuō)明。
針對實(shí)時(shí)性的解決方案
uClinux本身并沒(méi)有關(guān)注實(shí)時(shí)問(wèn)題,它并不是為了Linux的實(shí)時(shí)性而提出的。另外有一種Linux--Rt-linux關(guān)注實(shí)時(shí)問(wèn)題。Rt-linux執行管理器把普通 Linux 的內核當成一個(gè)任務(wù)運行,同時(shí)還管理了實(shí)時(shí)進(jìn)程。而非實(shí)時(shí)進(jìn)程則交給普通Linux內核處理。這種方法已經(jīng)應用于很多的操作系統用于增強操作系統的實(shí)時(shí)性,包括一些商用版UNIX系統,Windows NT等等。這種方法優(yōu)點(diǎn)之一是實(shí)現簡(jiǎn)單,且實(shí)時(shí)性能容易檢驗。優(yōu)點(diǎn)之二是由于非實(shí)時(shí)進(jìn)程運行于標準Linux系統,同其它Linux商用版本之間保持了很大的兼容性。優(yōu)點(diǎn)之三是可以支持硬實(shí)時(shí)時(shí)鐘的應用。uClinux可以使用Rt-linux的patch,從而增強uClinux的實(shí)時(shí)性,使得uClinux可以應用于工業(yè)控制、進(jìn)程控制等一些實(shí)時(shí)要求較高的應用。
uClinux的內存管理
應該說(shuō)uClinux同標準Linux的最大區別就在于內存管理,同時(shí)也由于uClinux的內存管理引發(fā)了一些標準Linux所不會(huì )出現的問(wèn)題。本文將把uClinux內存管理同標準Linux的那內存管理部分進(jìn)行比較分析。
1、標準Linux使用的虛擬存儲器技術(shù)
標準Linux使用虛擬存儲器技術(shù),這種技術(shù)用于提供比計算機系統中實(shí)際使用的物理內存大得多的內存空間。使用者將感覺(jué)到好像程序可以使用非常大的內存空間,從而使得編程人員在寫(xiě)程序時(shí)不用考慮計算機中的物理內存的實(shí)際容量。
為了支持虛擬存儲管理器的管理,Linux系統采用分頁(yè)(paging)的方式來(lái)載入進(jìn)程。所謂分頁(yè)既是把實(shí)際的存儲器分割為相同大小的段,例如每個(gè)段1024個(gè)字節,這樣1024個(gè)字節大小的段便稱(chēng)為一個(gè)頁(yè)面(page)。
虛擬存儲器由存儲器管理機制及一個(gè)大容量的快速硬盤(pán)存儲器支持。它的實(shí)現基于局部性原理,當一個(gè)程序在運行之前,沒(méi)有必要全部裝入內存,而是僅將那些當前要運行的那些部分頁(yè)面或段裝入內存運行(copy-on-write),其余暫時(shí)留在硬盤(pán)上程序運行時(shí)如果它所要訪(fǎng)問(wèn)的頁(yè)(段)已存在,則程序繼續運行,如果發(fā)現不存在的頁(yè)(段),操作系統將產(chǎn)生一個(gè)頁(yè)錯誤(pagefault),這個(gè)錯誤導致操作系統把需要運行的部分加載到內存中。必要時(shí)操作系統還可以把不需要的內存頁(yè)(段)交換到磁盤(pán)上。利用這樣的方式管理存儲器,便可把一個(gè)進(jìn)程所需要用到的存儲器以化整為零的方式,視需求分批載入,而核心程序則憑借屬于每個(gè)頁(yè)面的頁(yè)碼來(lái)完成尋址各個(gè)存儲器區段的工作。
標準Linux是針對有內存管理單元的處理器設計的。在這種處理器上,虛擬地址被送到內存管理單元(MMU),把虛擬地址映射為物理地址。
通過(guò)賦予每個(gè)任務(wù)不同的虛擬--物理地址轉換映射,支持不同任務(wù)之間的保護。地址轉換函數在每一個(gè)任務(wù)中定義,在一個(gè)任務(wù)中的虛擬地址空間映射到物理內存的一個(gè)部分,而另一個(gè)任務(wù)的虛擬地址空間映射到物理存儲器中的另外區域。計算機的存儲管理單元(MMU)一般有一組寄存器來(lái)標識當前運行的進(jìn)程的轉換表。在當前進(jìn)程將CPU放棄給另一個(gè)進(jìn)程時(shí)(一次上下文切換),內核通過(guò)指向新進(jìn)程地址轉換表的指針加載這些寄存器。MMU寄存器是有特權的,只能在內核態(tài)才能訪(fǎng)問(wèn)。這就保證了一個(gè)進(jìn)程只能訪(fǎng)問(wèn)自己用戶(hù)空間內的地址,而不會(huì )訪(fǎng)問(wèn)和修改其它進(jìn)程的空間。當可執行文件被加載時(shí),加載器根據缺省的ld文件,把程序加載到虛擬內存的一個(gè)空間,因為這個(gè)原因實(shí)際上很多程序的虛擬地址空間是相同的,但是由于轉換函數不同,所以實(shí)際所處的內存區域也不同。而對于多進(jìn)程管理當處理器進(jìn)行進(jìn)程切換并執行一個(gè)新任務(wù)時(shí),一個(gè)重要部分就是為新任務(wù)切換任務(wù)轉換表。我們可以看到Linux系統的內存管理至少實(shí)現了以下功能:
運行比內存還要大的程序。理想情況下應該可以運行任意大小的程序:
可以運行只加載了部分的程序,縮短了程序啟動(dòng)的時(shí)間
可以使多個(gè)程序同時(shí)駐留在內存中提高CPU的利用率
可以運行重定位程序。即程序可以方于內存中的任何一處,而且可以在執行過(guò)程中移動(dòng)。
寫(xiě)機器無(wú)關(guān)的代碼。程序不必事先約定機器的配置情況。
減輕程序員分配和管理內存資源的負擔。
可以進(jìn)行共享--例如,如果兩個(gè)進(jìn)程運行同一個(gè)程序,它們應該可以共享程序代碼的同一個(gè)副本。
提供內存保護,進(jìn)程不能以非授權方式訪(fǎng)問(wèn)或修改頁(yè)面,內核保護單個(gè)進(jìn)程的數據和代碼以防止其它進(jìn)程修改它們。否則,用戶(hù)程序可能會(huì )偶然(或惡意)的破壞內核或其它用戶(hù)程序。
虛存系統并不是沒(méi)有代價(jià)的。 內存管理需要地址轉換表和其他一些數據結構,留給程序的內存減少了。地址轉換增加了每一條指令的執行時(shí)間,而對于有額外內存操作的指令會(huì )更嚴重。當進(jìn)程訪(fǎng)問(wèn)不在內存的頁(yè)面時(shí),系統發(fā)生失效。系統處理該失效,并將頁(yè)面加載到內存中,這需要極耗時(shí)間的磁盤(pán)I/O操作??傊畠却婀芾砘顒?dòng)占用了相當一部分cpu時(shí)間(在較忙的系統中大約占10%)。
2、uClinux針對NOMMU的特殊處理
對于uClinux來(lái)說(shuō),其設計針對沒(méi)有MMU的處理器,即uClinux不能使用處理器的虛擬內存管理技術(shù)(應該說(shuō)這種不帶有MMU的處理器在嵌入式設備中相當普偏)。uClinux仍然采用存儲器的分頁(yè)管理,系統在啟動(dòng)時(shí)把實(shí)際存儲器進(jìn)行分頁(yè)。在加載應用程序時(shí)程序分頁(yè)加載。但是由于沒(méi)有MMU管理,所以實(shí)際上uClinux采用實(shí)存儲器管理策略(real memeory management)。這一點(diǎn)影響了系統工作的很多方面。
uClinux系統對于內存的訪(fǎng)問(wèn)是直接的,(它對地址的訪(fǎng)問(wèn)不需要經(jīng)過(guò)MMU,而是直接送到地址線(xiàn)上輸出),所有程序中訪(fǎng)問(wèn)的地址都是實(shí)際的物理地址。操作系統對內存空間沒(méi)有保護(這實(shí)際上是很多嵌入式系統的特點(diǎn)),各個(gè)進(jìn)程實(shí)際上共享一個(gè)運行空間(沒(méi)有獨立的地址轉換表)。
一個(gè)進(jìn)程在執行前, 系統必須為進(jìn)程分配足夠的連續地址空間,然后全部載入主存儲器的連續空間中。與之相對應的是標準Linux系統在分配內存時(shí)沒(méi)有必要保證實(shí)際物理存儲空間是連續的,而只要保證虛存地址空間連續就可以了。另外一個(gè)方面程序加載地址與預期(ld文件中指出的)通常都不相同,這樣relocation過(guò)程就是必須的。此外磁盤(pán)交換空間也是無(wú)法使用的,系統執行時(shí)如果缺少內存將無(wú)法通過(guò)磁盤(pán)交換來(lái)得到改善。
uClinux對內存的管理減少同時(shí)就給開(kāi)發(fā)人員提出了更高的要求。如果從易用性這一點(diǎn)來(lái)說(shuō),uClinux的內存管理是一種倒退,退回了到了Unix早期或是Dos系統時(shí)代。開(kāi)發(fā)人員不得不參與系統的內存管理。從編譯內核開(kāi)始,開(kāi)發(fā)人員必須告訴系統這塊開(kāi)發(fā)板到底擁有多少的內存(假如你欺騙了系統,那將在后面運行程序時(shí)受到懲罰),從而系統將在啟動(dòng)的初始化階段對內存進(jìn)行分頁(yè),并且標記已使用的和未使用的內存。系統將在運行應用時(shí)使用這些分頁(yè)內存。
由于應用程序加載時(shí)必須分配連續的地址空間,而針對不同硬件平臺的可一次成塊(連續地址)分配內存大小限制是不同(目前針對ez328處理器的uClinux是128k,而針對coldfire處理器的系統內存則無(wú)此限制),所以開(kāi)發(fā)人員在開(kāi)發(fā)應用程序時(shí)必須考慮內存的分配情況并關(guān)注應用程序需要運行空間的大小。另外由于采用實(shí)存儲器管理策略,用戶(hù)程序同內核以及其它用戶(hù)程序在一個(gè)地址空間,程序開(kāi)發(fā)時(shí)要保證不侵犯其它程序的地址空間,以使得程序不至于破壞系統的正常工作,或導致其它程序的運行異常。
從內存的訪(fǎng)問(wèn)角度來(lái)看,開(kāi)發(fā)人員的權利增大了(開(kāi)發(fā)人員在編程時(shí)可以訪(fǎng)問(wèn)任意的地址空間),但與此同時(shí)系統的安全性也大為下降。此外,系統對多進(jìn)程的管理將有很大的變化,這一點(diǎn)將在uClinux的多進(jìn)程管理中說(shuō)明。
雖然uClinux的內存管理與標準Linux系統相比功能相差很多,但應該說(shuō)這是嵌入式設備的選擇。在嵌入式設備中,由于成本等敏感因素的影響,普偏的采用不帶有MMU的處理器,這決定了系統沒(méi)有足夠的硬件支持實(shí)現虛擬存儲管理技術(shù)。從嵌入式設備實(shí)現的功能來(lái)看,嵌入式設備通常在某一特定的環(huán)境下運行,只要實(shí)現特定的功能,其功能相對簡(jiǎn)單,內存管理的要求完全可以由開(kāi)發(fā)人員考慮。
3、標準Linux系統的進(jìn)程、線(xiàn)程
進(jìn)程:進(jìn)程是一個(gè)運行程序并為其提供執行環(huán)境的實(shí)體,它包括一個(gè)地址空間和至少一個(gè)控制點(diǎn),進(jìn)程在這個(gè)地址空間上執行單一指令序列。進(jìn)程地址空間包括可以訪(fǎng)問(wèn)或引用的內存單元的集合,進(jìn)程控制點(diǎn)通過(guò)一個(gè)一般稱(chēng)為程序計數器(program counter,PC)的硬件寄存器控制和跟蹤進(jìn)程指令序列。
fork:由于進(jìn)程為執行程序的環(huán)境,因此在執行程序前必須先建立這個(gè)能跑程序的環(huán)境。Linux系統提供系統調用拷貝現行進(jìn)程的內容,以產(chǎn)生新的進(jìn)程,調用fork的進(jìn)程稱(chēng)為父進(jìn)程;而所產(chǎn)生的新進(jìn)程則稱(chēng)為子進(jìn)程。子進(jìn)程會(huì )承襲父進(jìn)程的一切特性,但是它有自己的數據段,也就是說(shuō),盡管子進(jìn)程改變了所屬的變量,卻不會(huì )影響到父進(jìn)程的變量值。
父進(jìn)程和子進(jìn)程共享一個(gè)程序段,但是各自擁有自己的堆棧、數據段、用戶(hù)空間以及進(jìn)程控制塊。換言之,兩個(gè)進(jìn)程執行的程序代碼是一樣的,但是各有各的程序計數器與自己的私人數據。
當內核收到fork請求時(shí),它會(huì )先查核三件事:首先檢查存儲器是不是足夠;其次是進(jìn)程表是否仍有空缺;最后則是看看用戶(hù)是否建立了太多的子進(jìn)程。如果上述說(shuō)三個(gè)條件滿(mǎn)足,那么操作系統會(huì )給子進(jìn)程一個(gè)進(jìn)程識別碼,并且設定cpu時(shí)間,接著(zhù)設定與父進(jìn)程共享的段,同時(shí)將父進(jìn)程的inode拷貝一份給子進(jìn)程運用,最終子進(jìn)程會(huì )返回數值0以表示它是子進(jìn)程,至于父進(jìn)程,它可能等待子進(jìn)程的執行結束,或與子進(jìn)程各做個(gè)的。
exec系統調用:該系統調用提供一個(gè)進(jìn)程去執行另一個(gè)進(jìn)程的能力,exec系統調用是采用覆蓋舊有進(jìn)程存儲器內容的方式,所以原來(lái)程序的堆棧、數據段與程序段都會(huì )被修改,只有用戶(hù)區維持不變。
vfork系統調用:由于在使用fork時(shí),內核會(huì )將父進(jìn)程拷貝一份給子進(jìn)程,但是這樣的做法相當浪費時(shí)間,因為大多數的情形都是程序在調用fork后就立即調用exec,這樣剛拷貝來(lái)的進(jìn)程區域又立即被新的數據覆蓋掉。因此Linux系統提供一個(gè)系統調用vfork,vfork假定系統在調用完成vfork后會(huì )馬上執行exec,因此vfork不拷貝父進(jìn)程的頁(yè)面,只是初始化私有的數據結構與準備足夠的分頁(yè)表。這樣實(shí)際在vfork調用完成后父子進(jìn)程事實(shí)上共享同一塊存儲器(在子進(jìn)程調用exec或是exit之前),因此子進(jìn)程可以更改父進(jìn)程的數據及堆棧信息,因此vfork系統調用完成后,父進(jìn)程進(jìn)入睡眠,直到子進(jìn)程執行exec。當子進(jìn)程執行exec時(shí),由于exec要使用被執行程序的數據,代碼覆蓋子進(jìn)程的存儲區域,這樣將產(chǎn)生寫(xiě)保護錯誤(do_wp_page)(這個(gè)時(shí)候子進(jìn)程寫(xiě)的實(shí)際上是父進(jìn)程的存儲區域),這個(gè)錯誤導致內核為子進(jìn)程重新分配存儲空間。當子進(jìn)程正確開(kāi)始執行后,將喚醒父進(jìn)程,使得父進(jìn)程繼續往后執行。
4、uClinux的多進(jìn)程處理
uClinux沒(méi)有mmu管理存儲器,在實(shí)現多個(gè)進(jìn)程時(shí)(fork調用生成子進(jìn)程)需要實(shí)現數據保護。
uClinux的fork和vfork:uClinux的fork等于vfork。實(shí)際上uClinux的多進(jìn)程管理通過(guò)vfork來(lái)實(shí)現。這意味著(zhù)uClinux系統fork調用完程后,要么子進(jìn)程代替父進(jìn)程執行(此時(shí)父進(jìn)程已經(jīng)sleep)直到子進(jìn)程調用exit退出,要么調用exec執行一個(gè)新的進(jìn)程,這個(gè)時(shí)候將產(chǎn)生可執行文件的加載,即使這個(gè)進(jìn)程只是父進(jìn)程的拷貝,這個(gè)過(guò)程也不能避免。當子進(jìn)程執行exit或exec后,子進(jìn)程使用wakeup把父進(jìn)程喚醒,父進(jìn)程繼續往下執行。
uClinux的這種多進(jìn)程實(shí)現機制同它的內存管理緊密相關(guān)。uClinux針對nommu處理器開(kāi)發(fā),所以被迫使用一種flat方式的內存管理模式,啟動(dòng)新的應用程序時(shí)系統必須為應用程序分配存儲空間,并立即把應用程序加載到內存。缺少了MMU的內存重映射機制,uClinux必須在可執行文件加載階段對可執行文件reloc處理,使得程序執行時(shí)能夠直接使用物理內存。
評論