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
















評(píng)論