新時代高科技不計其數越來越發達,小伙伴們看過不少科技新聞吧,在我們生活中應該也用到很多這些高科技東西,有哪些小伙伴值的關注的呢,今天就跟大家分享一篇有關科技方面知識,希望大家會喜歡。
今天來說一下關于uCLinux是什么及uCLinux有什么用這方面的一些訊息,不少朋友對于uCLinux是什么及uCLinux有什么用這方面的信息頗感興趣的。小編今天就為此整理一些相關的訊息,希望對有需要的朋友有所幫助。
uCLinux 表示 micro-control linux.即“微控制器領域中的 Linux 系統”,是 Lineo 公司的主打產品,同時也是開放源碼的嵌入式 Linux 的典范之作。uCLinux 主要是針對目標處理器沒有存儲管理單元 MMU(Memory Management Unit)的嵌入式系統而設計的。它已經被成功地移植到了很多平臺上。由于沒有 MMU,其多任務的實現需要一定技巧。
uclinux
簡介
Linux 是一種很受歡迎的操作系統,它與 UNIX 系統兼容,開放源代碼。它原本被設計為桌面系統,現在廣泛應用于服務器領域。而更大的影響在于它正逐漸的應用于嵌入式設備。uClinux 正是在這種氛圍下產生的。在 uClinux 這個英文單詞中 u 表示 Micro,小的意思,C 表示 Control,控制的意思,所以 uClinux 就是 Micro-Control-Linux,字面上的理解就是”針對微控制領域而設計的 Linux 系統”。
uClinux 是嵌入式 Linux 領域非常重要的分支,已成功應用于路由器、機頂盒、PDA 等領域,與標準 Linux 在內存管理方面有著本質的區別。
uCLinux 是一種優秀的嵌入式 Linux 版本,是 micro-Controller-Linux 的縮寫。它秉承了標準 Linux 的優良特性, 經過各方面的小型化改造,形成了一個高度優化的、代碼緊湊的嵌入式 Linux。雖然它的體積很小,卻仍然保留了 Linux 的大多數的優點:穩定、良好的移植性、優秀的網絡功能、對各種文件系統完備的支持和標準豐富的 API。它專為嵌入式系統做了許多小型化的工作,目前已支持多款 CPU。 其編譯后目標文件可控制在幾百 KB 數量級,并已經被成功地移植到很多平臺上。
uClinux 從 Linux 2.0/2.4 內核派生而來,沿襲了 Linux 的絕大部分特性。它是專門針對沒有 MMU(內存管理單元)的 CPU,并且為嵌入式系統做了許多小型化的工作。它通常用于具有很少內存或 Flash 的嵌入式操作系統。在 GNU 通用許可證的保證下,運行 uClinux 操作系統的用戶可以使用幾乎所有的 Linux API 函數。由于經過了裁剪和優化,它形成了一個高度優化,代碼緊湊的嵌入式 Linux。它具有體積小、穩定、良好的移植性、優秀的網絡功能、完備的對各種文件系統的支持,以及豐富的 API 函數等優點。uClinux 與 Linux 在兼容性方面表現出色,uClinux 除了不能實現 fork()外,其余 uClinux 的 API 函數與標準 Linux 完全相同。
針對沒有 MMU 的 CPU
全球每年生產的 CPU 的數量大概在二十億顆左右,其中大部分是應用于專用性很強的各類嵌入式系統。大部分嵌入式系統為了減少系統復雜程度、降低硬件及開發成本和運行功耗,在硬件設計中取消了內存管理單元(MMU)模塊。最初,運行于這類沒有 MMU 的 CPU 之上的都是一些很簡單的單任務操作系統,或者更簡單的控制程序,甚至根本就沒有操作系統而直接運行應用程序。在這種情況下,系統無法運行復雜的應用程序,或者效率很低,并且所有的應用程序需要重新開發,還要求開發人員十分了解硬件特性。這些都阻礙了不含 MMU 的嵌入式產品開發的速度和應用水平。
uClinux 專門針對沒有 MMU 的 CPU,并且為嵌入式系統做了許多小型化的工作。uClinux 是一個完全符合 GNU/GPL 公約的項目,完全開放代碼。
最初的 uClinux 僅僅支持 Palm 硬件系統,基于 Linux 2.0 內核。隨著系統的日益改進,支持的內核版本從 2.0、2.2、2.4 一直到現在最新的 2.6。系統的開發人員從兩人增加到了目前的 12 人,支持的硬件系統也從一種增加到了目前的十余種(支持的硬件平臺如 Motorola 公司的 M68328、M68EN322、MC68360、DragonBall 系列如 68EZ328、68VZ328,ColdFire 系列的如 5272、5307,ARM 7TDMI、MC68EN302、ETRAX、Intel i960、PRISMA、Atari 68k 等等。)
根據 Linuxdevices 網站 2004 年 3 月的調查,uClinux 在全球嵌入式 Linux 市場所占的份額已位居第二,僅僅落后于定制 Linux(即自己下載源碼進行修改定制)。同時 Linux 在全球嵌入式操作系統的市場份額依然處于統治地位(占 40%以上),領先第二名微軟公司的嵌入式操作系統三倍以上(市場份額約 13%)。
特點
標準 Linux 可能采用的小型化方法
1. 重新編譯內核
Linux 內核采用模塊化的設計,即很多功能塊可以獨立的加上或卸下,開發人員在設計內核時把這些內核模塊作為可選的選項,可以在編譯系統內核時指定。因此一種較通用的做法是對 Linux 內核重新編譯,在編譯時仔細的選擇嵌入式設備所需要的功能支持模塊,同時刪除不需要的功能。通過對內核的重新配置,可以使系統運行所需要的內核顯著減小,從而縮減資源使用量。
2. 制作 root 文件系統映象
Linux 系統在啟動時必須加載根(root)文件系統,因此剪裁系統同時包括 root file system 的剪裁。在 x86 系統下,Linux 可以在 Dos 下,使用 Loadlin 文件加載啟動,
uClinux 采用的小型化方法
1.uClinux 的內核加載方式
uClinux 的內核有兩種可選的運行方式:可以在 flash 上直接運行,也可以加載到內存中運行。這種做法可以減少內存需要。
Flash 運行方式:把內核的可執行映象燒寫到 flash 上,系統啟動時從 flash 的某個地址開始逐句執行。這種方法實際上是很多嵌入式系統采用的方法。
內核加載方式:把內核的壓縮文件存放在 flash 上,系統啟動時讀取壓縮文件在內存里解壓,然后開始執行,這種方式相對復雜一些,但是運行速度可能更快(ram 的存取速率要比 flash 高)。同時這也是標準 Linux 系統采用的啟動方式。
2.uClinux 的根(root)文件系統
uClinux 系統采用 romfs 文件系統,這種文件系統相對于一般的 ext2 文件系統要求更少的空間。空間的節約來自于兩個方面,首先內核支持 romfs 文件系統比支持 ext2 文件系統需要更少的代碼,其次 romfs 文件系統相對簡單,在建立文件系統超級塊(superblock)需要更少的存儲空間。Romfs 文件系統不支持動態擦寫保存,對于系統需要動態保存的數據采用虛擬 ram 盤的方法進行處理(ram 盤將采用 ext2 文件系統)。
3.uClinux 的應用程序庫
uClinux 小型化的另一個做法是重寫了應用程序庫,相對于越來越大且越來越全的 glibc 庫,uClibc 對 libc 做了精簡。
uClinux 對用戶程序采用靜態連接的形式,這種做法會使應用程序變大,但是基于內存管理的問題,不得不這樣做(這將在下文對 uClinux 內存管理展開分析時進行說明),同時這種做法也更接近于通常嵌入式系統的做法。
系統特點
嵌入式操作系統比較
由表 1 可以看出,對于嵌入式應用,高端平臺可直接采用 Linux 系統,其兼容性和可移植度都較高,但對硬件處理速度和存儲空間要求較高。
低端平臺的最佳選擇是 uClinux,其性能穩定、移植性好、功能強大。
低端平臺如果對實時性要求較高、應用相對簡單,則可采用 uc/os 或其他操作系統。
基本架構
uClinux 的系統與標準 Linux 的架構完全一致。
文件系統
uClinux 系統多采用 Romfs 文件系統,Romfs 是一種相對簡單、占用空間較少的文件系統。空間的節約來自于兩個方面:首先內核支持 Romfs 文件系統比支持 ext2 文件系統需要更少的代碼;其次 romfs 文件系統相對簡單,在建立文件系統超級塊(Superblock)需要更少的存儲空間。Romfs 是只讀的文件系統,禁止寫操作,因此系統同時需要虛擬盤(RAMDISK)支持臨時文件和數據文件的存儲。
隨著技術的發展,近年來日志文件系統在 uClinux 系統上得到了較多的應用,其中以支持 NOR FLASH 的 JFFS、JFFS2 文件系統和支持 NAND FLASH 的 YAFFS 最為流行。這些文件系統都支持掉電文件保護,同時支持標準的 MTD 驅動。
開發環境
GNU 開發套件
Gnu 開發套件作為通用的 Linux 開放套件,包括一系列的開發調試工具。主要組件:
Gcc: 編譯器,可以做成交叉編譯的形式,即在宿主機上開發編譯目標上可運行的二進制文件。
Binutils:一些輔助工具,包括 objdump(可以反編譯二進制文件),as(匯編編譯器),ld(連接器)等等。
Gdb:調試器,可使用多種交叉調試方式,gdb-bdm(背景調試工具),gdbserver(使用以太網絡調試)。
uClinux 的打印終端
通常情況下,uClinux 的默認終端是串口,內核在啟動時所有的信息都打印到串口終端(使用 printk 函數打印),同時也可以通過串口終端與系統交互。
uClinux 在啟動時啟動了 telnetd(遠程登錄服務),操作者可以遠程登錄上系統,從而控制系統的運行。至于是否允許遠程登錄可以通過燒寫 romfs 文件系統時有用戶決定是否啟動遠程登錄服務。
交叉編譯調試工具
支持一種新的處理器,必須具備一些編譯,匯編工具,使用這些工具可以形成可運行于這種處理器的二進制文件。對于內核使用的編譯工具同應用程序使用的有所不同。在解釋不同點之前,需要對 gcc 連接做一些說明:
.ld(link description)文件:ld 文件是指出連接時內存映象格式的文件。
crt0.S:應用程序編譯連接時需要的啟動文件,主要是初始化應用程序棧。
pic:position independence code ,與位置無關的二進制格式文件,在程序段中必須包括 reloc 段,從而使的代碼加載時可以進行重新定位。
內核編譯連接時,使用 ucsimm.ld 文件,形成可執行文件映象,所形成的代碼段既可以使用間接尋址方式(即使用 reloc 段進行尋址),也可以使用絕對尋址方式。這樣可以給編譯器更多的優化空間。因為內核可能使用絕對尋址,所以內核加載到的內存地址空間必須與 ld 文件中給定的內存空間完全相同。
應用程序的連接與內核連接方式不同。應用程序由內核加載(可執行文件加載器將在后面討論),由于應用程序的 ld 文件給出的內存空間與應用程序實際被加載的內存位置可能不同,這樣在應用程序加載的過程中需要一個重新地位的過程,即對 reloc 段進行修正,使得程序進行間接尋址時不至于出錯。(這個問題在 i386 等高級處理器上方法有所不同,本文將在后面進一步分析)。
由上述討論,至少需要兩套編譯連接工具。在討論過 uClinux 的內存管理后本文將給出整個系統的工作流程以及系統在 flash 和 ram 中的空間分布。
可執行文件格式
先對一些名詞作一些說明:
coff(common object file format):一種通用的對象文件格式
elf(excutive linked file):一種為 Linux 系統所采用的通用文件格式,支持動態連接
flat:elf 格式有很大的文件頭,flat 文件對文件頭和一些段信息做了簡化
uClinux 系統使用 flat 可執行文件格式,gcc 的編譯器不能直接形成這種文件格式,但是可以形成 coff 或 elf 格式的可執行文件,這兩種文件需要 coff2flt 或 elf2flt 工具進行格式轉化,形成 flat 文件。
當用戶執行一個應用時,內核的執行文件加載器將對 flat 文件進行進一步處理,主要是對 reloc 段進行修正(可執行文件加載器的詳見 fs/binfmt_flat.c)。以下對 reloc 段進一步討論。
需要 reloc 段的根本原因是,程序在連接時連接器所假定的程序運行空間與實際程序加載到的內存空間不同。假如有這樣一條指令:
jsr app_start;
這一條指令采用直接尋址,跳轉到 app_start 地址處執行,連接程序將在編譯完成是計算出 app_start 的實際地址(設若實際地址為 0x10000),這個實際地址是根據 ld 文件計算出來(因為連接器假定該程序將被加載到由 ld 文件指明的內存空間)。但實際上由于內存分配的關系,操作系統在加載時無法保證程序將按 ld 文件加載。這時如果程序仍然跳轉到絕對地址 0x10000 處執行,通常情況這是不正確的。一個解決辦法是增加一個存儲空間,用于存儲 app_start 的實際地址,設若使用變量 addr 表示這個存儲空間。則以上這句程序將改為:
movl addr, a0;
jsr (a0);
增加的變量 addr 將在數據段中占用一個 4 字節的空間,連接器將 app_start 的絕對地址存儲到該變量。在可執行文件加載時,可執行文件加載器根據程序將要加載的內存空間計算出 app_start 在內存中的實際位置,寫入 addr 變量。系統在實際處理是不需要知道這個變量的確切存儲位置(也不可能知道),系統只要對整個 reloc 段進行處理就可以了(reloc 段有標識,系統可以讀出來)。處理很簡單只需要對 reloc 段中存儲的值統一加上一個偏置(如果加載的空間比預想的要靠前,實際上是減去一個偏移量)。偏置由實際的物理地址起始值同 ld 文件指定的地址起始值相減計算出。
這種 reloc 的方式部分是由 uClinux 的內存分配問題引起的,這一點將在 uClinux 內存管理分析時說明。
針對實時性的解決方案
uClinux 本身并沒有關注實時問題,它并不是為了 Linux 的實時性而提出的。另外有一種 Linux–Rt-linux 關注實時問題。Rt-linux 執行管理器把普通 Linux 的內核當成一個任務運行,同時還管理了實時進程。而非實時進程則交給普通 Linux 內核處理。這種方法已經應用于很多的操作系統用于增強操作系統的實時性,包括一些商用版 UNIX 系統,Windows NT 等等。這種方法優點之一是實現簡單,且實時性能容易檢驗。優點之二是由于非實時進程運行于標準 Linux 系統,同其它 Linux 商用版本之間保持了很大的兼容性。優點之三是可以支持硬實時時鐘的應用。uClinux 可以使用 Rt-linux 的 patch,從而增強 uClinux 的實時性,使得 uClinux 可以應用于工業控制、進程控制等一些實時要求較高的應用。
內存管理
應該說 uClinux 同標準 Linux 的最大區別就在于內存管理,同時也由于 uClinux 的內存管理引發了一些標準 Linux 所不會出現的問題。本文將把 uClinux 內存管理同標準 Linux 的內存管理部分進行比較分析。
標準 Linux 使用的虛擬存儲器技術
標準 Linux 使用虛擬存儲器技術,這種技術用于提供比計算機系統中實際使用的物理內存大得多的內存空間。使用者將感覺到好像程序可以使用非常大的內存空間,從而使得編程人員在寫程序時不用考慮計算機中的物理內存的實際容量。為了支持虛擬存儲管理器的管理,Linux 系統采用分頁(paging)的方式來載入進程。所謂分頁既是把實際的存儲器分割為相同大小的段,例如每個段 1024 個字節,這樣 1024 個字節大小的段便稱為一個頁面(page)。
虛擬存儲器由存儲器管理機制及一個大容量的快速硬盤存儲器支持。它的實現基于局部性原理,當一個程序在運行之前,沒有必要全部裝入內存,而是僅將那些當前要運行的那些部分頁面或段裝入內存運行(copy-on-write),其余暫時留在硬盤上程序運行時如果它所要訪問的頁(段)已存在,則程序繼續運行,如果發現不存在的頁(段),操作系統將產生一個頁錯誤(page fault),這個錯誤導致操作系統把需要運行的部分加載到內存中。必要時操作系統還可以把不需要的內存頁(段)交換到磁盤上。利用這樣的方式管理存儲器,便可把一個進程所需要用到的存儲器以化整為零的方式,視需求分批載入,而核心程序則憑借屬于每個頁面的頁碼來完成尋址各個存儲器區段的工作。
標準 Linux 是針對有內存管理單元的處理器設計的。在這種處理器上,虛擬地址被送到內存管理單元(MMU),把虛擬地址映射為物理地址。
通過賦予每個任務不同的虛擬–物理地址轉換映射,支持不同任務之間的保護。地址轉換函數在每一個任務中定義,在一個任務中的虛擬地址空間映射到物理內存的一個部分,而另一個任務的虛擬地址空間映射到物理存儲器中的另外區域。計算機的存儲管理單元(MMU)一般有一組寄存器來標識當前運行的進程的轉換表。在當前進程將 CPU 放棄給另一個進程時(一次上下文切換),內核通過指向新進程地址轉換表的指針加載這些寄存器。MMU 寄存器是有特權的,只能在內核態才能訪問。這就保證了一個進程只能訪問自己用戶空間內的地址,而不會訪問和修改其它進程的空間。當可執行文件被加載時,加載器根據缺省的 ld 文件,把程序加載到虛擬內存的一個空間,因為這個原因實際上很多程序的虛擬地址空間是相同的,但是由于轉換函數不同,所以實際所處的內存區域也不同。而對于多進程管理當處理器進行進程切換并執行一個新任務時,一個重要部分就是為新任務切換任務轉換表。我們可以看到 Linux 系統的內存管理至少實現了以下功能:
運行比內存還要大的程序。理想情況下應該可以運行任意大小的程序
◇可以運行只加載了部分的程序,縮短了程序啟動的時間
◇可以使多個程序同時駐留在內存中提高 CPU 的利用率
◇可以運行重定位程序。即程序可以方于內存中的任何一處,而且可以在執行過程中移動。
◇寫機器無關的代碼。程序不必事先約定機器的配置情況。
◇減輕程序員分配和管理內存資源的負擔。
◇可以進行共享–例如,如果兩個進程運行同一個程序,它們應該可以共享程序代碼的同一個副本。
◇提供內存保護,進程不能以非授權方式訪問或修改頁面,內核保護單個進程的數據和代碼以防止其它進程修改它們。否則,用戶程序可能會偶然(或惡意)的破壞內核或其它用戶程序。
虛存系統并不是沒有代價的。內存管理需要地址轉換表和其他一些數據結構,留給程序的內存減少了。地址轉換增加了每一條指令的執行時間,而對于有額外內存操作的指令會更嚴重。當進程訪問不在內存的頁面時,系統發生失效。系統處理該失效,并將頁面加載到內存中,這需要極耗時間的磁盤 I/O 操作。總之內存管理活動占用了相當一部分 cpu 時間(在較忙的系統中大約占 10%)。
uClinux 針對 NOMMU 的特殊處理
對于 uClinux 來說,其設計針對沒有 MMU 的處理器,即 uClinux 不能使用處理器的虛擬內存管理技術(應該說這種不帶有 MMU 的處理器在嵌入式設備中相當普偏)。uClinux 仍然采用存儲器的分頁管理,系統在啟動時把實際存儲器進行分頁。在加載應用程序時程序分頁加載。但是由于沒有 MMU 管理,所以實際上 uClinux 采用實存儲器管理策略(real memeory management)。這一點影響了系統工作的很多方面。
uClinux 系統對于內存的訪問是直接的,(它對地址的訪問不需要經過 MMU,而是直接送到地址線上輸出),所有程序中訪問的地址都是實際的物理地址。操作系統對內存空間沒有保護(這實際上是很多嵌入式系統的特點),各個進程實際上共享一個運行空間(沒有獨立的地址轉換表)。
一個進程在執行前,系統必須為進程分配足夠的連續地址空間,然后全部載入主存儲器的連續空間中。與之相對應的是標準 Linux 系統在分配內存時沒有必要保證實際物理存儲空間是連續的,而只要保證虛存地址空間連續就可以了。另外一個方面程序加載地址與預期(ld 文件中指出的)通常都不相同,這樣 relocation 過程就是必須的。此外磁盤交換空間也是無法使用的,系統執行時如果缺少內存將無法通過磁盤交換來得到改善。
uClinux 對內存的管理減少同時就給開發人員提出了更高的要求。如果從易用性這一點來說,uClinux 的內存管理是一種倒退,退回了到了 UNIX 早期或是 Dos 系統時代。開發人員不得不參與系統的內存管理。從編譯內核開始,開發人員必須告訴系統這塊開發板到底擁有多少的內存(假如你欺騙了系統,那將在后面運行程序時受到懲罰),從而系統將在啟動的初始化階段對內存進行分頁,并且標記已使用的和未使用的內存。系統將在運行應用時使用這些分頁內存。
由于應用程序加載時必須分配連續的地址空間,而針對不同硬件平臺的可一次成塊(連續地址)分配內存大小限制是不同(目前針對 ez328 處理器的 uClinux 是 128k,而針對 coldfire 處理器的系統內存則無此限制),所以開發人員在開發應用程序時必須考慮內存的分配情況并關注應用程序需要運行空間的大小。另外由于采用實存儲器管理策略,用戶程序同內核以及其它用戶程序在一個地址空間,程序開發時要保證不侵犯其它程序的地址空間,以使得程序不至于破壞系統的正常工作,或導致其它程序的運行異常。
從內存的訪問角度來看,開發人員的權利增大了(開發人員在編程時可以訪問任意的地址空間),但與此同時系統的安全性也大為下降。此外,系統對多進程的管理將有很大的變化,這一點將在 uClinux 的多進程管理中說明。
雖然 uClinux 的內存管理與標準 Linux 系統相比功能相差很多,但應該說這是嵌入式設備的選擇。在嵌入式設備中,由于成本等敏感因素的影響,普偏的采用不帶有 MMU 的處理器,這決定了系統沒有足夠的硬件支持實現虛擬存儲管理技術。從嵌入式設備實現的功能來看,嵌入式設備通常在某一特定的環境下運行,只要實現特定的功能,其功能相對簡單,內存管理的要求完全可以由開發人員考慮。
標準 Linux 系統的進程、線程
進程:進程是一個運行程序并為其提供執行環境的實體,它包括一個地址空間和至少一個控制點,進程在這個地址空間上執行單一指令序列。進程地址空間包括可以訪問或引用的內存單元的集合,進程控制點通過一個一般稱為程序計數器(program counter,PC)的硬件寄存器控制和跟蹤進程指令序列。
fork:由于進程為執行程序的環境,因此在執行程序前必須先建立這個能”跑”程序的環境。Linux 系統提供系統調用拷貝現行進程的內容,以產生新的進程,調用 fork 的進程稱為父進程;而所產生的新進程則稱為子進程。子進程會承襲父進程的一切特性,但是它有自己的數據段,也就是說,盡管子進程改變了所屬的變量,卻不會影響到父進程的變量值。
父進程和子進程共享一個程序段,但是各自擁有自己的堆棧、數據段、用戶空間以及進程控制塊。換言之,兩個進程執行的程序代碼是一樣的,但是各有各的程序計數器與自己的私人數據。
當內核收到 fork 請求時,它會先查核三件事:首先檢查存儲器是不是足夠;其次是進程表是否仍有空缺;最后則是看看用戶是否建立了太多的子進程。如果上述說三個條件滿足,那么操作系統會給子進程一個進程識別碼,并且設定 cpu 時間,接著設定與父進程共享的段,同時將父進程的 inode 拷貝一份給子進程運用,最終子進程會返回數值 0 以表示它是子進程,至于父進程,它可能等待子進程的執行結束,或與子進程各做個的。
exec 系統調用:該系統調用提供一個進程去執行另一個進程的能力,exec 系統調用是??序的堆棧、數據段與程序段都會被修改,只有用戶區維持不變。
vfork 系統調用:由于在使用 fork 時,內核會將父進程拷貝一份給子進程,但是這樣的做法相當浪費時間,因為大多數的情形都是程序在調用 fork 后就立即調用 exec,這樣剛拷貝來的進程區域又立即被新的數據覆蓋掉。因此 Linux 系統提供一個系統調用 vfork,vfork 假定系統在調用完成 vfork 后會馬上執行 exec,因此 vfork 不拷貝父進程的頁面,只是初始化私有的數據結構與準備足夠的分頁表。這樣實際在 vfork 調用完成后父子進程事實上共享同一塊存儲器(在子進程調用 exec 或是 exit 之前),因此子進程可以更改父進程的數據及堆棧信息,因此 vfork 系統調用完成后,父進程進入睡眠,直到子進程執行 exec。當子進程執行 exec 時,由于 exec 要使用被執行程序的數據,代碼覆蓋子進程的存儲區域,這樣將產生寫保護錯誤(do_wp_page)(這個時候子進程寫的實際上是父進程的存儲區域),
這個錯誤導致內核為子進程重新分配存儲空間。當子進程正確開始執行后,將喚醒父進程,使得父進程繼續往后執行。
uClinux 的多進程處理
uClinux 沒有 mmu 管理存儲器,在實現多個進程時(fork 調用生成子進程)需要實現數據保護。
uClinux 的 fork 和 vfork:uClinux 的 fork 等于 vfork。實際上 uClinux 的多進程管理通過 vfork 來實現。這意味著 uClinux 系統 fork 調用完程后,要么子進程代替父進程執行(此時父進程已經 sleep)直到子進程調用 exit 退出,要么調用 exec 執行一個新的進程,這個時候將產生可執行文件的加載,即使這個進程只是父進程的拷貝,這個過程也不能避免。當子進程執行 exit 或 exec 后,子進程使用 wakeup 把父進程喚醒,父進程繼續往下執行。
uClinux 的這種多進程實現機制同它的內存管理緊密相關。uClinux 針對 nommu 處理器開發,所以被迫使用一種 flat 方式的內存管理模式,啟動新的應用程序時系統必須為應用程序分配存儲空間,并立即把應用程序加載到內存。缺少了 MMU 的內存重映射機制,uClinux 必須在可執行文件加載階段對可執行文件 reloc 處理,使得程序執行時能夠直接使用物理內存。
uClinux 是專門針對沒有 MMU 的處理器而設計的,即 uClinux 無法使用處理器的虛擬內存管理技術。實際上 uClinux 采用實存儲器管理策略,通過地址總線對物理內存進行直接訪問。所有程序中訪問的地址都是實際的物理地址,所有的進程都在一個運行空間中運行(包括內核進程),這樣的運行機制給程序員帶來了不小的挑戰,在操作系統不提供保護的情況下必需小心設計程序和數據空間,以免引起應用程序進程甚至是內核的崩潰。
uClinux 仍然采用存儲器的分頁管理,系統在啟動時把實際存儲器進行分頁,在加載應用程序時程序分頁加載。一個進程在執行前,系統必須為進程分配足夠的連續地址空間,然后全部載入主存儲器的連續空間中。系統不含 MMU 帶來的另外一個問題是磁盤交換空間無法使用,對于資源有限的嵌入式系統而言,系統執行時如果缺少內存將無法通過磁盤交換來得到改善。
MMU 的省略雖然帶來了系統及應用程序開發的限制,但對于成本和體積敏感的嵌入式設備而言,其應用環境和應用需求并不要求復雜和相對昂貴的硬件體系,對于功能簡單的專用嵌入式設備,內存的分配和管理完全可以由開發人員考慮。
多進程管理
由于 uClinux 沒有 MMU 管理存儲器,在實現多個進程時需要實現數據保護。uClinux 的雖然支持 fork 函數,但其實質是和 vfork:實際上 uClinux 所有的多進程管理都通過 vfork 來實現。
vfork 不拷貝父進程的頁面,只是初始化私有的數據結構與準備足夠的分頁表。調用完成后父子進程事實上共享同一塊存儲器,因此子進程可以更改父進程的數據及堆棧信息,所有父進程進入睡眠,直到子進程執行 exec。當子進程正確開始執行后,將喚醒父進程,使得父進程繼續往后執行。這意味著 uClinux 系統 fork 調用完成后,要么子進程代替父進程執行(此時父進程已經休眠)直到子進程調用 exit 退出,要么調用 exec 執行一個新的進程。
vfork 是 uClinux 與標準 Linux 應用程序的開發中最重要的不同之處,只有對 vfork 與 fork 兩個函數的差異和程序處理有詳細的了解才能順利地完成從 Linux 到 uClinux 的程序移植。
缺點
正如中國古語云“人無完人”,uClinux 也有一些不足之處:
文檔的不足
與 Linux 及其他自由軟件類似,uClinux 的文檔十分不足:缺乏組織和一致的文檔、熱門技術和分類文檔眾多而雜亂無章、非熱點部分文檔缺失甚至沒有文檔。對于開發人員而言,往往要深入程序的源代碼找尋有用的資料。
Bug 問題
uClinux 與硬件平臺直接相關。對于有商業公司贊助的硬件平臺,其相關代碼和 Bug 更新較快,編譯和執行都十分順利;但對于非商業支持的硬件平臺,其內核和應用程序代碼都得不到及時更新和排錯。這種現象在內核源代碼樹還不是十分普遍,但在 uClinux 自帶的應用程序庫中卻經常發生編譯錯誤,往往是增加了一個應用程序或改變了運行庫便導致無法編譯。這就需要開發者投入足夠的時間和精力進行排錯和修改,也會導致開發進度的延誤。
以上就是關于uCLinux是什么及uCLinux有什么用這方面的一些信息了 小編整理的這些訊息希望對童鞋們有所幫助