1、概述
操作系統(tǒng)的內(nèi)存管理功能用于向操作系統(tǒng)提供一致的地址映射功能和內(nèi)存頁面的申請、釋放操作。在嵌入式實時系統(tǒng)中,內(nèi)存管理根據(jù)不同的系統(tǒng),有不同的策略,對于有些系統(tǒng)支持的虛擬內(nèi)存管理機制,對于另外一些系統(tǒng),可能只有flat式的簡單內(nèi)存管理機制。
2、內(nèi)存管理機制:
大體上來說,嵌入式系統(tǒng)所用到的內(nèi)存管理機制主要有以下兩種:
(1)??虛擬內(nèi)存管理機制:
有一些嵌入式處理器提供了MMU,在MMU具備內(nèi)存地址映射和尋址功能,它使操作系統(tǒng)的內(nèi)存管理更加方便。如果存在MMU ,操作系統(tǒng)會使用它完成從虛擬地址到物理地址的轉(zhuǎn)換, 所有的應(yīng)用程序只需要使用虛擬地址尋址數(shù)據(jù)。 這種使用虛擬地址尋址整個系統(tǒng)的主存和輔存的方式在現(xiàn)代操作系統(tǒng)中被稱為虛擬內(nèi)存。MMU 便是實現(xiàn)虛擬內(nèi)存的必要條件。
虛擬內(nèi)存的管理方法使系統(tǒng)既可以運行體積比物理內(nèi)存還要大的應(yīng)用程序,也可以實現(xiàn)“按需調(diào)頁”策略,既滿足了程序的運行速度,又節(jié)約了物理內(nèi)存空間。
在L inux系統(tǒng)中,虛擬內(nèi)存機制的實現(xiàn)實現(xiàn)為我們提供了一個典型的例子:在不同的體系結(jié)構(gòu)下, 使用了三級或者兩級頁式管理,利用MMU 完成從虛擬地址到物理地址之間的轉(zhuǎn)換。基于虛擬內(nèi)存管理的內(nèi)存最大好處是:由于不同進程有自己單獨的進程空間,十分有效的提高了系統(tǒng)可靠性和安全性。
(2)??非虛擬內(nèi)存管理機制
在實時性要求比較高的情況下,很多嵌入式系統(tǒng)并不需要虛擬內(nèi)存機制:因為虛擬內(nèi)存機制會導(dǎo)致不確定性的 I/O阻塞時間, 使得程序運行時間不可預(yù)期,這是實時嵌入式系統(tǒng)的致命缺陷;另外,從嵌入式處理器的成本考慮,大多采用不裝配MMU 的嵌入式微處理器。所以大多嵌入式系統(tǒng)采用的是實存儲器管理策略。因而對于內(nèi)存的訪問是直接的,它對地址的訪問不需要經(jīng)過MMU,而是直接送到地址線上輸出,所有程序中訪問的地址都是實際的物理地址;而且,大多數(shù)嵌入式操作系統(tǒng)對內(nèi)存空間沒有保護,各個進程實際上共享一個運行空間。一個進程在執(zhí)行前,系統(tǒng)必須為它分配足夠的連續(xù)地址空間,然后全部載入主存儲器的連續(xù)空間。
由此可見,嵌入式系統(tǒng)的開發(fā)人員不得不參與系統(tǒng)的內(nèi)存管理。從編譯內(nèi)核開始,開發(fā)人員必須告訴系統(tǒng)這塊開發(fā)板到底擁有多少內(nèi)存;在開發(fā)應(yīng)用程序時,必須考慮內(nèi)存的分配情況并關(guān)注應(yīng)用程序需要運行空間的大小。另外,由于采用實存儲器管理策略,用戶程序同內(nèi)核以及其它用戶程序在一個地址空間,程序開發(fā)時要保證不侵犯其它程序的地址空間,以使得程序不至于破壞系統(tǒng)的正常工作,或?qū)е缕渌绦虻倪\行異常;因而,嵌入式系統(tǒng)的開發(fā)人員對軟件中的一些內(nèi)存操作要格外小心。
UCOS就是使用非虛擬內(nèi)存管理的一個例子,在UCOS中,所有的任務(wù)共享所有的物理內(nèi)存,任務(wù)之間沒有內(nèi)存保護機制,這樣能夠提高系統(tǒng)的相應(yīng)時間,但是任務(wù)內(nèi)存操作不當(dāng),會引起系統(tǒng)崩潰。
3、內(nèi)存在系統(tǒng)中的生命期:
對于內(nèi)存在整個嵌入式運行過程中,以3中方式存在:
1)、 在bootstraping 階段,內(nèi)存以臨時內(nèi)存分配的形式出現(xiàn),當(dāng)完成系統(tǒng)啟動后,這些內(nèi)存會回收供以后系統(tǒng)使用。
2)、 在正常運行階段,內(nèi)存以兩種方式存在:
( 1) 系統(tǒng)為代碼,數(shù)據(jù)分配的永久內(nèi)存,這些內(nèi)存在系統(tǒng)運行過程中是不會改變的,有的硬件的I/O等外設(shè)也把相應(yīng)的地址映射到固定的內(nèi)存空間。
( 2) 動態(tài)內(nèi)存分配空間:這些內(nèi)存不會固定分配,而是根據(jù)系統(tǒng)需要而動態(tài)分配的,如果利用非虛擬內(nèi)存管理機制,一般需要改造動態(tài)內(nèi)存分配機制以提高性能。
4、內(nèi)存管理的具體應(yīng)用:
A、Linux系統(tǒng)的內(nèi)存管理機制
Linux內(nèi)存管理機制中,X86體系結(jié)構(gòu)是利用虛擬內(nèi)存管理的典型,在i386CPU上,首先要進行段式映射,Linux 沒有用到段式管理,它的做法是把GDT中段描述符段的大小定義為4GB, 也就是說只分了一段, 從而使段式映射沒有起作用。在頁式映射中,對于嵌入式i386芯片來說,實際上是兩層映射, 跳過中間的PMD層次。對于程序來說,并非所有虛存都映射都到物理空間了,而是動態(tài)映射,如果程序運行時內(nèi)核發(fā)現(xiàn)虛擬頁面沒有映射或映射的是磁盤頁面, 會作相應(yīng)的缺頁處理——分配內(nèi)存頁面并建立映射,然后恢復(fù)程序運行。
在程序運行的過程中,涉及到的內(nèi)存操作主要有內(nèi)存分配、內(nèi)存使用、內(nèi)存回收、內(nèi)存頁面換出、頁面換入。內(nèi)存分配會在管理區(qū)的空閑區(qū)進行, 通過Buddy算法在管理區(qū)的free_area 中獲得需要的內(nèi)存塊。如果內(nèi)存不足, 則會啟動Kswapd這個守護進程騰出部分物理內(nèi)存。除了被調(diào)用, Kswapd 進程還會定時啟動。Kswapd 的工作分兩部分:
( 1) 檢測物理內(nèi)存剩余的情況, 如果短缺, 則按LRU策略斷開active_list 隊列中部分可交換頁面的映射, 使頁面變?yōu)椴换钴S狀態(tài),鏈入inactive_clean_list隊列或者inactive_dirty_list隊列, 為換出做準(zhǔn)備。
( 2) 每次都執(zhí)行, 把inactive_ dirty_list 中的頁面寫入交換設(shè)備,并且回收一部分inactive_clean_list 中的頁面。
Linux系統(tǒng)虛擬內(nèi)存機制的屏蔽
由于虛擬內(nèi)存在時間上的不可預(yù)期性,對于實時性要求很高的系統(tǒng),必須屏蔽虛擬內(nèi)存機制。在uCLinux中就利用了這種技術(shù)一保證系統(tǒng)的實時性,下面是屏蔽虛擬內(nèi)存機制的思路:
為了滿足在工業(yè)控制中一些任務(wù)的實時性要求,必須屏蔽內(nèi)核的虛擬內(nèi)存管理機制以增強Linux的實時性。當(dāng)要更改內(nèi)核的某項機制時,一般不必大規(guī)模的改寫代碼,可采用條件編譯的方法。思路是用#ifdef或 #ifndef屏蔽現(xiàn)有語句,在#else宏編譯語句中包括自己編寫的代碼。實現(xiàn)虛擬內(nèi)存的機制有:地址映射機制、內(nèi)存分配和回收機制,緩存和刷新機制、請頁機制、交換機制、內(nèi)存共享機制,將實現(xiàn)這些機制的數(shù)據(jù)結(jié)構(gòu)和函數(shù)屏蔽或修改,還要修改與之相關(guān)的文件。需要改動的文件主要在 /include/linux、/mm、/drivers/char、/fs、/ipc/kernel、/init目錄下。主要的改動如下:與虛存有關(guān)的主要的數(shù)據(jù)結(jié)構(gòu)是vm_area_struct,將進程的mm_struct結(jié)構(gòu)中的vm_area_struct去掉,vm_area_struct利用了vm_ops來抽象出對虛擬內(nèi)存的處理方法,屏蔽與虛擬內(nèi)存操作有關(guān)的函數(shù)。內(nèi)存映射主要由do_mmap()實現(xiàn),改寫此函數(shù)的代碼。取消交換操作,屏蔽用于交換的結(jié)構(gòu)和函數(shù)聲明,以及實現(xiàn)交換的代碼。取消內(nèi)核守護進程kswapd。
B、UCOS的內(nèi)存管理:
UCOS的內(nèi)存管理與大多數(shù)嵌入式系統(tǒng)一樣,是flat內(nèi)存,但在此flat內(nèi)存的基礎(chǔ)上進行了優(yōu)化,使在動態(tài)內(nèi)存分配的時候,減少了內(nèi)存粹片,提高了系統(tǒng)性能。
UCOS的具體方法是:把連續(xù)的大塊內(nèi)存進行分區(qū),每個分區(qū)包含整數(shù)個大小相同的內(nèi)存塊,在一個系統(tǒng)中有多個不同內(nèi)存大小的分區(qū)。這樣,應(yīng)用程序根據(jù)不同的需求,從不同大小的內(nèi)存分區(qū)中分配相應(yīng)大小的內(nèi)存。對于不用的內(nèi)存,又重新釋放回原來的分區(qū)。通過這樣的內(nèi)存管理算法,解決了內(nèi)存粹片的問題,提高了系統(tǒng)性能。UCOS具體的實現(xiàn)可以參看源碼。主要由以下幾個函數(shù)實現(xiàn):
OSMemCreate():創(chuàng)建內(nèi)存分區(qū)。
OSMenGet() :為應(yīng)用程序分配一段內(nèi)存。
OSMenPut():回收應(yīng)用程序不再使用的內(nèi)存。
5、結(jié)論:
內(nèi)存管理是嵌入式系統(tǒng)的一個重要方面,虛擬內(nèi)存管理機制在為進程安全提供很好保證的同時,也為開發(fā)人員提供了一個管理內(nèi)存的方法,使開發(fā)人員更多的關(guān)注其他的方面。但是它也帶來了時間不確定性的缺陷。根據(jù)不同的系統(tǒng)需求,我們可以選取相應(yīng)的內(nèi)存管理策略。在現(xiàn)在大多數(shù)的實時系統(tǒng)中,非虛擬內(nèi)存管理機制用得比較多,這樣保證了系統(tǒng)的實時性,但是增加了開發(fā)的難度,任務(wù)內(nèi)存操作不當(dāng),可能引起系統(tǒng)崩潰。
由于虛擬內(nèi)存管理的請求換頁機制在很大程度上影響了系統(tǒng)的實時性能,現(xiàn)在有些開發(fā)人員提出了一個折衷方案,即不用虛擬內(nèi)存管理的請求換頁機制,只考慮進程保護、內(nèi)存映射、共享虛擬內(nèi)存等功能,這樣既能提高系統(tǒng)的實時性,又能提高系統(tǒng)的安全性,具體請參考文獻(xiàn)4。
參考文獻(xiàn):
1、基于Linux的嵌入式系統(tǒng)在測控系統(tǒng)中的設(shè)計
2、The Linux kernel Primer.
3、嵌入式L inux 操作系統(tǒng)的研究.? 劉文峰, 李程遠(yuǎn), 李善平
4、嵌入式軟件虛擬內(nèi)存管理技術(shù)的研究和實現(xiàn). 錢 靜, 蘆東昕, 謝 鑫, 徐立鋒
5、Understanding the Linux kernel.
評論
查看更多