嵌入式操作系統(tǒng):第6章 嵌入式Linux的內(nèi)存管理_第1頁
嵌入式操作系統(tǒng):第6章 嵌入式Linux的內(nèi)存管理_第2頁
嵌入式操作系統(tǒng):第6章 嵌入式Linux的內(nèi)存管理_第3頁
嵌入式操作系統(tǒng):第6章 嵌入式Linux的內(nèi)存管理_第4頁
嵌入式操作系統(tǒng):第6章 嵌入式Linux的內(nèi)存管理_第5頁
已閱讀5頁,還剩33頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第6章嵌入式Linux的內(nèi)存管理本章教學(xué)目的及要求 了解Linux內(nèi)存管理的基本概念及相關(guān)數(shù)據(jù)結(jié)構(gòu) 了解虛存空間的管理 掌握共享內(nèi)存的操作 理解嵌入式操作系統(tǒng)內(nèi)存管理 理解動(dòng)態(tài)內(nèi)存分配及malloc/free的實(shí)現(xiàn) 了解Linux內(nèi)存的使用

內(nèi)存管理機(jī)制是嵌入式系統(tǒng)中的一個(gè)重點(diǎn)和難點(diǎn),它必須滿足以下幾個(gè)特性:實(shí)時(shí)性可靠性高效性 在嵌入式實(shí)時(shí)系統(tǒng)中,內(nèi)存管理根據(jù)不同的系統(tǒng),有不同的策略,對(duì)于有些系統(tǒng)支持的虛擬內(nèi)存管理機(jī)制,對(duì)于另外一些系統(tǒng),可能只有flat式的簡單內(nèi)存管理機(jī)制。6.1Linux內(nèi)存管理的基本概念及相關(guān)數(shù)據(jù)結(jié)構(gòu)6.1.1嵌入式操作系統(tǒng)內(nèi)存管理機(jī)制1.嵌入式操作系統(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)存的必要條件。 (2)非虛擬內(nèi)存管理機(jī)制

由于虛擬內(nèi)存機(jī)制會(huì)導(dǎo)致不確定性的I/O阻塞時(shí)間,使得程序運(yùn)行時(shí)間不可預(yù)期。在實(shí)時(shí)性要求較高時(shí),很多嵌入式系統(tǒng)不需要虛擬內(nèi)存機(jī)制。另外,從嵌入式處理器的成本考慮,大多采用不裝配MMU的嵌入式微處理器。采用實(shí)存儲(chǔ)器管理策略時(shí),對(duì)于內(nèi)存的訪問是直接的,它對(duì)地址的訪問不需要經(jīng)過MMU,而是直接送到地址線上輸出,所有程序中訪問的地址都是實(shí)際的物理地址;同時(shí),大多數(shù)嵌入式操作系統(tǒng)對(duì)內(nèi)存空間沒有保護(hù),各個(gè)進(jìn)程實(shí)際上共享一個(gè)運(yùn)行空間。2.內(nèi)存在系統(tǒng)中的生命期 (1)在啟動(dòng)階段,內(nèi)存以臨時(shí)分配的形式出現(xiàn),當(dāng)完成系統(tǒng)啟動(dòng)后,這些內(nèi)存會(huì)回收供以后系統(tǒng)使用。 (2)在正常運(yùn)行階段,內(nèi)存以兩種方式存在: ①系統(tǒng)為代碼,數(shù)據(jù)分配的永久內(nèi)存,這些內(nèi)存在系統(tǒng)運(yùn)行過程中是不會(huì)改變的,有的硬件的I/O等外設(shè)也把相應(yīng)的地址映射到固定的內(nèi)存空間。 ②動(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ī)制以提高性能。 3.Linux系統(tǒng)的內(nèi)存管理機(jī)制

Linux內(nèi)核的設(shè)計(jì)并沒有全部采用Intel所提供的段機(jī)制,僅僅是有限度地使用了分段機(jī)制。這不僅簡化了Linux內(nèi)核的設(shè)計(jì),而且為把Linux移植到其他平臺(tái)創(chuàng)造了條件,因?yàn)楹芏郣ISC處理器并不支持段機(jī)制。 所有段的基地址均為0。由此可以得出,每個(gè)段的邏輯地址空間范圍為0-4GB。因?yàn)槊總€(gè)段的基地址為0,因此,邏輯地址到線性地址映射保持不變,在Linux中所提到的邏輯地址和線性地址(或虛擬地址)指的也就是同一地址。Linux巧妙地把段機(jī)制給繞過去了,而完全利用了分頁機(jī)制。4.Linux系統(tǒng)虛擬內(nèi)存機(jī)制的屏蔽

屏蔽虛擬內(nèi)存機(jī)制的思路: 實(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)的文件。

虛擬內(nèi)存管理機(jī)制在為進(jìn)程安全提供很好保證的同時(shí),也為開發(fā)人員提供了一個(gè)管理內(nèi)存的方法,使開發(fā)人員更多的關(guān)注其他的方面。但是它也帶來了時(shí)間不確定性的缺陷。根據(jù)不同的系統(tǒng)需求,可以選取相應(yīng)的內(nèi)存管理策略?,F(xiàn)在大多數(shù)的實(shí)時(shí)系統(tǒng)中,非虛擬內(nèi)存管理機(jī)制用得比較多,這樣保證了系統(tǒng)的實(shí)時(shí)性,但是增加了開發(fā)的難度,任務(wù)內(nèi)存操作不當(dāng),可能引起系統(tǒng)崩潰。內(nèi)存管理程序提供以下功能:大地址空間:用戶程序使用的內(nèi)存數(shù)量可以超過物理上實(shí)際所有的內(nèi)存數(shù)量。內(nèi)存保護(hù):進(jìn)程的內(nèi)存是私有的,不能被其他進(jìn)程所讀取和修改。而且,內(nèi)存管理程序可以防止進(jìn)程覆蓋代碼和只讀數(shù)據(jù)。內(nèi)存映射:可以把一個(gè)文件映射到虛擬內(nèi)存區(qū)域,并把該文件當(dāng)做內(nèi)存來訪問。對(duì)物理內(nèi)存的公平訪問:內(nèi)存管理程序確保所有的進(jìn)程都能公平地訪問計(jì)算機(jī)的內(nèi)存資源,這樣可以確保理想的系統(tǒng)性能。共享虛擬內(nèi)存:內(nèi)存管理程序允許進(jìn)程共享它們內(nèi)存的一部分。6.1.2Linux內(nèi)存管理基礎(chǔ)知識(shí) 內(nèi)存管理的基本概念(1)存儲(chǔ)空間在32位嵌入式系統(tǒng)中,存儲(chǔ)空間的地址范圍從0x00000000到0xFFFFFFFF。這4GB存儲(chǔ)范圍內(nèi)可以包括以下幾種存儲(chǔ)空間.設(shè)備空間、內(nèi)部高速SRAM空間、內(nèi)部minicache空間、低端中斷向量空間、高端中斷向量空間、RAM內(nèi)存空間、ROM(flash)空間。(2)內(nèi)存空間系統(tǒng)的內(nèi)存空間特指上面的RAM內(nèi)存空間。(3)內(nèi)存頁(page)Linux是以頁(page)為單位來管理物理內(nèi)存的,一頁大小一般等于4096(字節(jié))。頁容量越大,系統(tǒng)中可能存在的內(nèi)存碎片就越多。(4)內(nèi)存區(qū)段(bank)一個(gè)內(nèi)存bank表示一塊連續(xù)內(nèi)存區(qū)域,一個(gè)bank一般對(duì)應(yīng)處理器的一個(gè)RAM片選管腳上連接的RAM芯片內(nèi)存空間。(5)內(nèi)存節(jié)點(diǎn)(node)內(nèi)存節(jié)點(diǎn)是指有一個(gè)或者多個(gè)內(nèi)存bank組成的內(nèi)存集合,如果一個(gè)內(nèi)存節(jié)點(diǎn)由多個(gè)內(nèi)存bank組成,這些內(nèi)存bank之間可以地址連續(xù),也可以不連續(xù),即內(nèi)存節(jié)點(diǎn)內(nèi)可以存在內(nèi)存孔洞。 內(nèi)存管理的基本概念(6)內(nèi)存頁區(qū)(zone)內(nèi)存頁區(qū)是定義在內(nèi)存節(jié)點(diǎn)(node)內(nèi)的概念,每個(gè)內(nèi)存節(jié)點(diǎn)可分為3個(gè)內(nèi)存頁區(qū),即DMA頁區(qū)(ZONE_DMA=0)、Normal頁區(qū)(ZONE_NORMAL=1)和HighMem頁區(qū)(ZONE_HIGHMEM=2),三個(gè)頁區(qū)的含義如下: ①

DMA頁區(qū):可以進(jìn)行DMA操作的RAM內(nèi)存區(qū)域。 ②

Normal頁區(qū):不能進(jìn)行DMA操作的RAM內(nèi)存區(qū)域。 ③

HighMem頁區(qū):屬于高端內(nèi)存的區(qū)域,高端內(nèi)存是指系統(tǒng)中的物理內(nèi)存容量太大,其中高于一定域值的RAM內(nèi)存頁區(qū)就是高端內(nèi)存頁區(qū)。(7)空閑內(nèi)存區(qū)域(freearea)對(duì)應(yīng)內(nèi)存空閑區(qū)域的重要數(shù)據(jù)結(jié)構(gòu)有struct

free_area。(8)NUMA(Non-UniformMemoryAccess)非一致內(nèi)存訪問。NUMA是一種分布式存儲(chǔ)器訪問方式,處理器可以同時(shí)訪問不同的存儲(chǔ)器地址,大幅提高并行性。如:內(nèi)存頁描述符結(jié)構(gòu)如下,structpage{

page_flags_tflags;頁標(biāo)志字

atomic_t_count;

atomic_t_mapcount;unsignedlongprivate;

struct

address_space*mapping;

pgoff_tindex;

struct

list_head

lru;#ifdefined(WneANT_PAGE_VIRTUAL)void*virtual;#endif/*WANT_PAGE_VIRTUAL*/};6.1.3Linux內(nèi)存管理相關(guān)數(shù)據(jù)結(jié)構(gòu)1.硬件物理內(nèi)存相關(guān)的數(shù)據(jù)結(jié)構(gòu)與函數(shù)(1)虛存區(qū)間vm_area_struct

,變量名通常為vma。(2)Vm_area_struct中的vm_mm指向一個(gè)mm_struct數(shù)據(jù)結(jié)構(gòu),變量名通常為mm;mm->segments為指向該進(jìn)程的局部段描述符表LDT。(3)Find_vma()找到一個(gè)包含addr的虛存頁面。(4)Insert_vm_struct向進(jìn)程的虛擬頁面隊(duì)列中插入一個(gè)虛存頁面(linux內(nèi)核的鏈表插入采用雙重鏈表指針)。(5)Swap_info_struct

相當(dāng)于page結(jié)構(gòu)。(6)Swap_entry_t

相當(dāng)于pte_t結(jié)構(gòu)。(7)SWP_TYPE(x)頁面所在的文件。(8)SWP_OFFSET(x)頁面在文件中的偏移。(9)SWP_ENTRY(type,offset)獲得swap_entry_t?!?.1.3Linux內(nèi)存管理相關(guān)數(shù)據(jù)結(jié)構(gòu)2.虛擬內(nèi)存相關(guān)的數(shù)據(jù)結(jié)構(gòu)與函數(shù)(1).text 存放CPU執(zhí)行的機(jī)器指令,代碼區(qū)通常是只讀的,防止程序意外地修改了它的指令。(2).data 該區(qū)包含被初始化的全局變量、靜態(tài)變量.它們是在編譯階段被編譯器存放在可執(zhí)行目標(biāo)文件的.data段中的.(3).BSS 未被初始化的全局變量和靜態(tài)局部變量,編譯的時(shí)候并未被分配空間,僅僅在.bss段中標(biāo)記它們,當(dāng)程序運(yùn)行的時(shí)候才為它們?cè)趦?nèi)存中分配空間,并把它們初始化為零或空指針(NULL)。(4).rodata 該區(qū)包含常量數(shù)據(jù)(如字符串常量)在編譯階段被編譯器存放在可執(zhí)行目標(biāo)文件的.rodata段中的。6.2

Linux的進(jìn)程與內(nèi)存管理6.2.1進(jìn)程內(nèi)存管理可執(zhí)行程序存儲(chǔ)結(jié)構(gòu)程序運(yùn)行時(shí)內(nèi)存結(jié)構(gòu)(1)代碼區(qū)(text)

代碼區(qū)指令根據(jù)程序設(shè)計(jì)流程依次執(zhí)行,對(duì)于順序指令,則只會(huì)執(zhí)行一次(每個(gè)進(jìn)程),如果反復(fù),則需要使用跳轉(zhuǎn)指令,如果進(jìn)行遞歸,則需要借助棧來實(shí)現(xiàn)。(2)全局初始化數(shù)據(jù)區(qū)/靜態(tài)數(shù)據(jù)區(qū)(data):只初始化一次(3)未初始化數(shù)據(jù)區(qū)(BSS):在運(yùn)行時(shí)改變其值。(4)棧區(qū)(stack):由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值、局部變量的值等。(5)堆區(qū)(heap):用于動(dòng)態(tài)內(nèi)存分配。一般由程序員分配和釋放,若程序員不釋放,程序結(jié)束時(shí)有可能由OS回收。

程序執(zhí)行時(shí)的內(nèi)存分配情況inta=0;//a在全局已初始化數(shù)據(jù)區(qū)char*p1;//p1在BSS區(qū)(未初始化全局變量)main(){intb;//b在棧區(qū)chars[]="abc";//s為數(shù)組變量,存儲(chǔ)在棧區(qū),//“abc”為字符串常量,存儲(chǔ)在已初始化數(shù)據(jù)區(qū)char*p1,p2;//p1、p2在棧區(qū)char*p3="123456";//123456\0data數(shù)據(jù)區(qū),p3在棧區(qū).staticintc=0;//c為局部靜態(tài)數(shù)據(jù),data數(shù)據(jù)區(qū)p1=(char*)malloc(10);//分配得來的10個(gè)字節(jié)的區(qū)域在堆區(qū)p2=(char*)malloc(20);//分配得來的20個(gè)字節(jié)的區(qū)域在堆區(qū)free(p1);free(p2);}棧和堆的區(qū)別(1)管理方式不同

棧編譯器自動(dòng)管理,無需程序員手工控制;而堆空間的申請(qǐng)釋放工作由程序員控制,容易產(chǎn)生內(nèi)存泄漏。(2)空間大小不同。棧是向低地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存區(qū)域。因此,用戶從棧獲得的空間較小。堆是向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域。堆獲得的空間較靈活,也較大。進(jìn)程內(nèi)存空間Linux操作系統(tǒng)采用虛擬內(nèi)存管理技術(shù),使得每個(gè)進(jìn)程都有獨(dú)立的進(jìn)程地址空間,該空間是大小為3G,用戶看到和接觸的都是虛擬地址,無法看到實(shí)際的物理地址。利用這種虛擬地址不但能起到保護(hù)操作系統(tǒng)的作用,而且更重要的是用戶程序可使用比實(shí)際物理內(nèi)存更大的地址空間。Linux將4G的虛擬地址空間劃分為兩個(gè)部分——用戶空間與內(nèi)核空間。用戶空間從0到0xbfffffff,內(nèi)核空間從3G到4G。用戶進(jìn)程通常情況下只能訪問用戶空間的虛擬地址,不能訪問內(nèi)核空間。例外情況是用戶進(jìn)程通過系統(tǒng)調(diào)用訪問內(nèi)核空間。用戶空間對(duì)應(yīng)進(jìn)程,所以每當(dāng)進(jìn)程切換,用戶空間就會(huì)跟著變化。每個(gè)進(jìn)程的用戶空間都是完全獨(dú)立、互不相干的。內(nèi)存分配方式(1)靜態(tài)分配:編譯器在處理程序源代碼時(shí)分配,靜態(tài)對(duì)象是有名字的變量,可以直接對(duì)其進(jìn)行操作,靜態(tài)對(duì)象的分配與釋放由編譯器自動(dòng)處理。(2)動(dòng)態(tài)分配:程序在執(zhí)行時(shí)調(diào)用malloc

庫函數(shù)申請(qǐng)分配,動(dòng)態(tài)對(duì)象需要通過指針間接地進(jìn)行操作,分配與釋放必須由程序員顯式地管理。內(nèi)存分配方式創(chuàng)建進(jìn)程fork()、程序載入execv()、動(dòng)態(tài)內(nèi)存分配malloc()等進(jìn)程相關(guān)操作都需要分配內(nèi)存給進(jìn)程。這時(shí)進(jìn)程申請(qǐng)和獲得的不是物理地址,僅僅是虛擬地址。實(shí)際的物理內(nèi)存只有當(dāng)進(jìn)程真的去訪問新獲取的虛擬地址時(shí),才會(huì)由“請(qǐng)頁機(jī)制”產(chǎn)生“缺頁”異常,從而進(jìn)入分配實(shí)際頁框的程序。該異常是虛擬內(nèi)存機(jī)制賴以存在的基本保證——它會(huì)告訴內(nèi)核去為進(jìn)程分配物理頁,并建立對(duì)應(yīng)的頁表,這之后虛擬地址才實(shí)實(shí)在在地映射到了物理地址上。6.2.2系統(tǒng)物理內(nèi)存管理Linux2.6.29內(nèi)核為每種CPU提供統(tǒng)一的界面,采用了四級(jí)頁管理架構(gòu),來兼容二級(jí)、三級(jí)、四級(jí)管理架構(gòu)的CPU。Linux頁式管理這四級(jí)分別為:(1).頁全局目錄(PageGlobalDirectory):即pgd,是多級(jí)頁表的抽象最高層。(2).頁上級(jí)目錄(PageUpperDirectory):即pud。(3).頁中間目錄(PageMiddleDirectory):即pmd,是頁表的中間層。(4).頁表(PageTableEntry):即pte。Linux通過伙伴算法管理和分配頁。用戶空間和內(nèi)核空間內(nèi)存使用Linux內(nèi)核內(nèi)存使用1.Slab分配器Linux內(nèi)核中有許多內(nèi)存動(dòng)態(tài)分配的需求,而其中的對(duì)象大小也參差不齊,Linux內(nèi)核提供了slab層,扮演了通用數(shù)據(jù)結(jié)構(gòu)緩存層的角色。slab層根據(jù)對(duì)象的類型來分組不同的cache,每個(gè)cache存放不同類型的對(duì)象,例如一個(gè)cache被用來存儲(chǔ)task_struct,而另一個(gè)存放inode等。這些cache包含幾個(gè)slab,而slab由一個(gè)或多個(gè)物理上連續(xù)的page組成。對(duì)于一般的數(shù)據(jù)結(jié)構(gòu),每個(gè)slab只有一個(gè)頁即可。每個(gè)slab都包含一些對(duì)象成員,即被管理的數(shù)據(jù)結(jié)構(gòu)。系統(tǒng)分配對(duì)象時(shí)就從slab中取得。首先從這個(gè)cache中部分滿的slab中分配,如果沒有這樣的slab,便從空的slab中分配,如果也沒有,就創(chuàng)建一個(gè)新的slab來分配即可。因?yàn)槊總€(gè)slab是包含同一種對(duì)象的cache塊,它對(duì)對(duì)象的分配和釋放會(huì)變得更為容易和快速。另外,由于每個(gè)對(duì)象在釋放時(shí)幾乎處于分配好并且初始化好的狀態(tài),還可以節(jié)省不少初始化的時(shí)間。比如說分配inode變量,首先要一塊malloc(sizeof(inode))大小的內(nèi)存,然后初始化inode中的數(shù)據(jù)成員,在使用完畢后用free釋放分配的內(nèi)存。實(shí)際上,在free之后內(nèi)存中的內(nèi)容和剛剛初始化時(shí)差不多,比如說inode的引用計(jì)數(shù)count一定是降為零等等。Linux內(nèi)核內(nèi)存使用1.Slab分配器kernel有許多數(shù)據(jù)結(jié)構(gòu)都是還原到和初始化時(shí)一樣的時(shí)候才會(huì)free掉,例如一個(gè)mutex

lock初始化時(shí)和釋放時(shí)都處于unlock狀態(tài)。因此,只要在cache初始化的時(shí)候就將對(duì)象置于合法狀態(tài),以后每次分配對(duì)象的這些field一定是確定的,從而不必重復(fù)初始化,可以節(jié)省不少開銷。為了這個(gè)目的,linux的kmem_cache_create中有一個(gè)參數(shù)ctor初始化函數(shù),可以被用作這一目的,但linux似乎并沒有使用slab的這一特性(因?yàn)樗鼪]用調(diào)用ctor函數(shù))。每個(gè)cache都用struct

kmem_cache_s表示,其中有一個(gè)重要的成員變量structkmem_list3lists。這個(gè)結(jié)構(gòu)體中存放了該cache中空、部分滿、滿的slab的隊(duì)列:slab描述符(struct

slab對(duì)象)本身也要占用內(nèi)存。它們可以放在slab自身開始的地方,或者在slab之外另行分配。slab分配器創(chuàng)建新的slab正是通過上面的頁分配器進(jìn)行的。Linux內(nèi)核內(nèi)存使用2.kmalloc核心的kmalloc內(nèi)存分配函數(shù)和應(yīng)用層的malloc函數(shù)很相似,只是這個(gè)函數(shù)運(yùn)行得很快-一除非它被阻塞。它不清零它獲得的內(nèi)存空間,分配給它的區(qū)域仍存放著原有的數(shù)據(jù)。kmalloc函數(shù)在<linux/slab.h>中定義,實(shí)際上,它是通過下一層的__kmalloc完成內(nèi)存分配的。staticvoid*kmalloc(size_tsize,intflags)void*__kmalloc(size_tsize,intflags)kmalloc函數(shù)的第一個(gè)參數(shù)是size(大小),第二個(gè)參數(shù),flags是優(yōu)先權(quán)參數(shù),它會(huì)使kmalloc函數(shù)在尋找空閑頁較困難時(shí)改變函數(shù)的行為。最常用的優(yōu)先權(quán)是GFP_KERNEL,它的意思是該內(nèi)存分配在內(nèi)部是通過調(diào)用get_free_pages來實(shí)現(xiàn)的,所以名字中帶GFP是由運(yùn)行在內(nèi)核態(tài)的進(jìn)程調(diào)用的。當(dāng)空閑內(nèi)存太少時(shí),kmalloc函數(shù)會(huì)使當(dāng)前進(jìn)程進(jìn)入睡眠,等待空閑頁的出現(xiàn)。新的頁面可以通過以下幾種途徑獲得。一種方法是換出其他頁:因?yàn)閷?duì)換需要時(shí)間,進(jìn)程會(huì)等待它完成,這時(shí)內(nèi)核可以調(diào)度執(zhí)行其他的任務(wù)。Linux內(nèi)核內(nèi)存使用3.Vmalloc在申請(qǐng)和釋放較小且連續(xù)的內(nèi)存空間時(shí),使用kmalloc()和kfree()在物理內(nèi)存中進(jìn)行分配。申請(qǐng)較大的內(nèi)存空間時(shí),使用vmalloc()。由vmalloc()申請(qǐng)的內(nèi)存空間在虛擬內(nèi)存中是連續(xù)的,它們映射到在物理內(nèi)存時(shí),可以使用不連續(xù)的物理頁面,而且僅把當(dāng)前訪問的部分放在物理頁面中。盡管這段區(qū)域在物理上可能是不連續(xù)的(要訪問其中的每個(gè)頁面都必須獨(dú)立地調(diào)用函數(shù)__get_free_page),內(nèi)核卻認(rèn)為它們?cè)诘刂飞鲜沁B續(xù)的。分配的內(nèi)存空間被映射進(jìn)入內(nèi)核數(shù)據(jù)段中,從用戶空間是不可見的-這一點(diǎn)上與其他分配技術(shù)不同。vmalloc發(fā)生錯(cuò)誤時(shí)返回0(NULL地址),成功時(shí)返回一個(gè)指向一個(gè)大小為size的線性地址空間的指針。Linux內(nèi)核內(nèi)存使用3.Vmalloc使用vmalloc時(shí)應(yīng)將<linux/vmalloc.h>包含進(jìn)來。與其他內(nèi)存分配函數(shù)不同的是,vmalloc返回很“高”的地址值-這些地址要高于物理內(nèi)存的頂部。正確使用vmalloc函數(shù)的場(chǎng)合是為軟件分配一大塊連續(xù)的用于緩沖的內(nèi)存區(qū)域。注意vmalloc的開銷要比__get_free_pages大,因?yàn)樗幚慝@取內(nèi)存還要建立頁表。因此,不值得用vmalloc函數(shù)只分配一頁的內(nèi)存空間。vmalloc分配的內(nèi)核虛擬內(nèi)存與kmalloc/__get_free_pages分配的內(nèi)核邏輯內(nèi)存位于不同的區(qū)間,不會(huì)重疊。因?yàn)閮?nèi)核空間被分區(qū)管理,各司其職。用戶空間被分配在0-3G,3G之后緊跟著是物理內(nèi)存映射區(qū)間,再后面才是vmalloc_start開始的用于vmalloc分配內(nèi)存的地址空間。Linux內(nèi)核內(nèi)存使用3.Vmalloc內(nèi)存分配區(qū)間示意圖用vmalloc分配得到的內(nèi)存空間用vfree函數(shù)來釋放,這就像是要用kfree函數(shù)來釋放kmalloc函數(shù)分配得到的內(nèi)存空間。6.3虛擬空間的管理內(nèi)核在“系統(tǒng)態(tài)”執(zhí)行,在這一級(jí)任何操作都可以執(zhí)行。而應(yīng)用程序則執(zhí)行在最低級(jí),所謂的“用戶態(tài)”,在這一級(jí)處理器禁止對(duì)硬件的直接訪問和對(duì)內(nèi)存的未授權(quán)訪問。模塊是在所謂的“內(nèi)核空間”中運(yùn)行的,而應(yīng)用程序則是在“用戶空間”中運(yùn)行的。它們分別引用不同的內(nèi)存映射,也就是程序代碼使用不同的“地址空間”。Linux通過系統(tǒng)調(diào)用和硬件中斷完成從用戶空間到內(nèi)核空間的控制轉(zhuǎn)移。6.3.1內(nèi)核空間和用戶空間6.3虛擬空間的管理一個(gè)虛存區(qū)域是虛存空間中一個(gè)連續(xù)的區(qū)域,在這個(gè)區(qū)域中的信息具有相同的操作和訪問特性。每個(gè)虛擬區(qū)域用一個(gè)vm_area_struct結(jié)構(gòu)體進(jìn)行描述,它定義在/include/linux/mm.h中。

struct

vm_area_struct{

struct

mm_struct*vm_mm;unsignedlongvm_start; unsignedlongvm_end;

pgprot_t

vm_page_prot; unsignedshortvm_flags; shortvm_avl_height; ……}系統(tǒng)為每個(gè)進(jìn)程提供了4GB的虛擬內(nèi)存空間。各個(gè)進(jìn)程的虛擬內(nèi)存彼此獨(dú)立。6.3.2進(jìn)程的虛擬區(qū)域6.4共享內(nèi)存共享內(nèi)存區(qū)域是被多個(gè)進(jìn)程共享的一部分物理內(nèi)存。如果多個(gè)進(jìn)程都把該內(nèi)存區(qū)域映射到自己的虛擬地址空間,則這些進(jìn)程就都可以直接訪問該共享內(nèi)存區(qū)域,從而可以通過該區(qū)域進(jìn)行通信。共享內(nèi)存是進(jìn)程間共享數(shù)據(jù)的一種最快的方法,一個(gè)進(jìn)程向共享內(nèi)存區(qū)域?qū)懭肓藬?shù)據(jù),共享這個(gè)內(nèi)存區(qū)域的所有進(jìn)程就可以立刻看到其中的內(nèi)容。這塊共享虛擬內(nèi)存的頁面,出現(xiàn)在每一個(gè)共享該頁面的進(jìn)程的頁表中。但是它不需要在所有進(jìn)程的虛擬內(nèi)存中都有相同的虛擬地址。Linux通過系統(tǒng)調(diào)用和硬件中斷完成從用戶空間到內(nèi)核空間的控制轉(zhuǎn)移。每一個(gè)新創(chuàng)建的共享內(nèi)存對(duì)象都用一個(gè)shmid_kernel數(shù)據(jù)結(jié)構(gòu)來表達(dá)。系統(tǒng)中所有的shmid_kernel數(shù)據(jù)結(jié)構(gòu)都保存在shm_segs向量表中,該向量表的每一個(gè)元素都是一個(gè)指向sh

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論