第4章-內存管理_第1頁
第4章-內存管理_第2頁
第4章-內存管理_第3頁
第4章-內存管理_第4頁
第4章-內存管理_第5頁
已閱讀5頁,還剩133頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第四章內存管理內存管理內存管理子系統是操作系統的重要組成部分,它的主要任務是:管理系統中的內存資源,提供高效地分配和回收內存資源的手段;提高內存的利用率,減少對內存的浪費,充分發揮內存的作用。Linux共實現了五個內存管理器,它們是:物理內存管理器內核內存管理器虛擬內存管理器內核虛擬內存管理器用戶空間內存管理器內存管理內核內存管理器虛擬內存管理器內核虛擬內存管理器物理內存管理器用戶內存管理器物理內存系統其余部分4.1物理內存管理器物理內存管理器管理的基本內存單位是物理頁,每個物理頁用一個page結構描述,所有的page結構組成一個mem_map[]數組。typedefstructpage{ structpage *next; structpage *prev; structinode *inode; unsignedlong offset; structpage *next_hash; //用于頁緩存 atomic_t count; unsignedlong flags; structwait_queue *wait; structpage **pprev_hash; //用于頁緩存 structbuffer_head *buffers;}mem_map_t;4.1物理內存管理器flags各位的意義位名稱意義0PG_locked加鎖1PG_error頁上出現I/O錯2PG_referenced正被引用3PG_dirty臟頁4PG_uptodate頁的內容是否有效5PG_free_after頁已寫完8PG_DMA能否用作DMA傳送9PG_Slab是否用做slab(內核內存管理器)31PG_reserved1:保留,0:可用4.1物理內存管理器系統中所有的空閑頁都記錄在數組free_area[]中。structfree_area_struct{ structpage*next; structpage*prev; unsignedint*map;};structfree_area_structfree_area[NR_MEM_LISTS];NR_MEM_LISTS的值是10或12。該數組已經建立并初始化。4.1物理內存管理器位圖map用于記錄頁塊及其伙伴是否在隊列中,兩個伙伴合用一位,其意義如下:1)如兩伙伴全都不在隊列中(已分配或已組成了更大的塊),它們合用的位為0;2)如一個伙伴在隊列中,一個不在隊列中,則它們合用的位為1;3)如兩個伙伴都在隊列中,則它們應該合并成更大的塊,加入到free_area[]數組中更上面的隊列,所以它們合用的位應為0;4)在free_area數組的最大一個隊列中,位圖無用。位圖的大小=物理頁數/2i位,i是隊列在數組free_area[]中的索引。(應該是物理頁數/2(i+1))。4.1物理內存管理器用第一個物理頁的page結構代表大小為2i頁的連續物理頁塊,用它的編號代表整個頁塊的編號。大小為2i、編號為map_nr的頁塊的伙伴是:map_nr^(-((~0)<<i))這兩個伙伴在位圖free_area[i]->map中共用的標志位是:(map_nr)>>(1+i)如:頁塊8、9、10、11(代表是8)的伙伴是12、13、14、15(代表是12),它們在位圖free_area[2]->map中共用第1位。4.1物理內存管理器04321765物理內存……3210mapmapmapmap4561free_area[]4.1物理內存管理器物理內存管理器使用向量表free_area[]來分配和回收物理頁。

全局變量nr_free_pages記錄系統中當前的空閑頁數。全局變量freepages為系統中的空閑物理內存劃了三條基準線。typedefstructfreepages_v1{ unsignedint min; unsignedint low; unsignedint high;}freepages_v1;typedeffreepages_v1 freepages_t;freepages_t freepages;

4.1物理內存管理器分配原則(該原則在不斷變化):當系統中空閑物理頁數少于freepages.min時,應該回收內存;一旦開始內存回收,每次分配前都要進行回收,直到系統中空閑物理頁數大于freepages.high;當系統中空閑物理頁數大于freepages.high時,每次都直接進行內存分配,直到空閑物理頁數再次小于freepages.min;當系統中空閑內存數大于freepages.high時,可以立刻進行內存分配。4.1.2物理頁分配物理內存管理器使用伙伴(Buddy)算法分配和釋放物理頁塊,頁塊大小為2i個頁。物理內存管理器返回的是在內核空間中看到的內存塊的起始地址(物理地址+0xC0000000)。物理內存的分配和釋放不影響頁目錄和頁表。分配函數是__get_free_pages,定義為:unsignedlong__get_free_pages(intgfp_mask,unsignedlongorder)gfp_mask是對內存的要求,order是申請的大小(2的指數)。4.1.2物理頁分配1、如果空閑物理內存較少(需要回收),則:1)喚醒內核交換守護進程kswapd。2)如果在gfp_mask中設置了__GFP_WAIT標志,則強行回收內存(自己調用回收函數)。2、如果不需要回收內存或已回收到了足夠的內存,則查free_area數組的第order列:如果其中有滿足要求的頁塊,則摘下一塊,修改位圖,累減nr_free_pages,返回物理頁塊的首地址。否則(隊列為空),向上搜索free_area數組:如果整個free_area數組中都沒有滿足要求的頁塊,則此次分配失敗,返回0。如果找到了一個滿足要求的頁塊,則將其從隊列中摘下、反復分割成伙伴,將一個大小適中的伙伴分配給用戶,其余伙伴加入free_area數組。同時修改位圖,累減變量nr_free_pages。4.1.2物理頁分配04321765物理內存……3210mapmapmapmap456free_area申請1頁4.1.2物理頁分配04321765物理內存……3210mapmapmapmap4、5566free_area4.1.3物理頁釋放在物理頁的釋放過程中,必須盡可能地按照伙伴算法合并頁塊。函數free_pages用于釋放頁塊,其定義如下:

voidfree_pages(unsignedlongaddr,unsignedlongorder)

addr是要釋放頁塊的首地址;order是要釋放頁塊的大小。4.1.3物理頁釋放1、根據首地址addr算出頁塊在mem_map[]中的索引map_nr(addr>>12),找到頁塊第一頁對應的page結構(mem_map[map_nr])。2、如果該頁塊是保留的,則不允許釋放,返回。3、將page結構的引用計數(page.count)減1。4、如果count>0,說明頁塊還有別的使用者,因此不能釋放它。返回。4.1.3物理頁釋放5、如果count=0,則釋放它:1)清除page結構的flags域中的PG_referenced位。2)累加變量nr_free_pages(加上回收的物理頁數)。3)將頁塊加入到數組free_area[]中:如果頁塊的伙伴不在隊列free_area[order]中,則將其直接插入隊列,修改位圖。返回。如果頁塊的伙伴在隊列中且order=NR_MEM_LISTS-1,則將其直接插入隊列。返回。如果頁塊的伙伴在隊列中但order<NR_MEM_LISTS-1,則將頁塊的伙伴從隊列中摘下、修改位圖,將它們合并成一個更大的頁塊,重新插入數組free_area[]中(遞歸)。4.1.3物理頁釋放04321765物理內存……3210mapmapmapmap4、5566free_area4.1.4物理頁回收內核交換守護進程kswapd負責物理頁的回收,從而保證系統有足夠的空閑頁。其主體如下:while(1){ do{ if(nr_free_pages>=freepages.high) break; //不需要回收內存 if(!do_try_to_free_pages(GFP_KSWAPD)) break; //沒有回收到內存 }while(!tsk->need_resched); run_task_queue(&tq_disk); //處理磁盤任務隊列 tsk->state=TASK_INTERRUPTIBLE; schedule_timeout(HZ); //睡眠100個滴答}4.1.4物理頁回收在函數do_try_to_free_pages中完成物理頁的回收工作。為了提高效率,該函數要嘗試多種回收手段,一次回收多個物理頁(SWAP_CLUSTER_MAX==32)。

為了公平起見,該函數采用時鐘算法搜索各種數據結構。不是每次都從頭開始,也不是每次都檢查完所有的結構。每次檢查的數據結構的個數由對物理內存的需求決定。如果系統中的空閑頁太少,就多檢查一些,否則就少檢查一些。4.1.4物理頁回收函數do_try_to_free_pages回收內存的順序如下:1、從內核內存管理器中回收空閑頁。

kmem_cache_reap(gfp_mask)

2、回收可廢棄的內存頁。

shrink_mmap(priority,gfp_mask)

順序搜索數組mem_map[],回收:在交換緩存中且已經不再使用的頁。用作buffer且所有buffer都不再使用的頁。在頁緩存中且沒有任何進程使用的頁。4.1.4物理頁回收3、回收共享內存頁。

shm_swap(priority,gfp_mask)

4、回收進程的虛擬內存,即將進程的某些頁交換到外存。

swap_out(priority,gfp_mask)

5、從目錄緩存中回收物理頁。

shrink_dcache_memory(priority,gfp_mask)

4.1物理內存管理器當物理內存較大時(超過1GB),上述方法需要擴充,為此引入zone的概念:zone是具有相同屬性的連續的物理頁。通常定義三個zone:1、ZONE_DMA:16MB以內,用于DMA。2、ZONE_NORMAL:16MB~896MB,用于普通物理內存,在內核中有虛擬地址。3、ZONE_HIGHMEM:大于896MB,用于高端物理內存,在內核中沒有虛擬地址。每個zone都有自己的free_area[]數組。4.1物理內存管理器隨著NUMA結構的出現,系統所管理的物理地址空間不再一致。對一個CPU來說,有的內存近,有的內存遠;有的速度快,有的速度慢。CPU希望使用盡可能一致的物理頁,尤其是對一次申請。為此引入節點(node)的概念。節點的描述結構是pglist_data,其中定義了該節點的管理區(zone)、各類需求(GFP標志)的分配策略(每策略最多有4個可選的zone,它們按優先級排序,分配時按順序搜索各zone并試圖從中分配物理頁)、其page結構數組等。系統中所有的節點組成一個隊列pgdat_list。

4.2內核內存管理器內核在運行的過程中,需要大量而頻繁地使用內存,如建立各種用于管理的數據結構、緩沖區等。這些內存有以下特點:尺寸一般都很小,遠遠小于一頁,如果直接使用物理內存管理器按頁管理,其利用率會非常低。要求動態分配和釋放,無法預測使用量。不參與交換(不在進程的虛擬地址空間,也不在交換緩存、頁緩存及Buffercache中,不會被換入、換出)。要求響應速度快,分配速度慢的管理器會導致整個系統性能的下降。4.2內核內存管理器內核內存管理器的種類:1、無內核內存管理器;2、資源映射圖分配器;3、簡單2次冪空閑表;4、McKusick-Karels分配器;5、伙伴系統;6、SVR4Lazy伙伴算法;7、Mach-OSF/1的Zone分配器;8、存儲桶(bucket);9、Solaris2.4的Slab分配器。Linux的內核內存管理器采用Slab分配器。4.2內核內存管理器cache_cachecache1cache2cache3……cachenslab1slab2slab3slab4s_freep物理頁對象對象對象對象4.2內核內存管理器(cache結構)structkmem_cache_s{ kmem_slab_t *c_freep; //第一個有空閑對象的slab unsignedlong c_flags; //標志 unsignedlong c_offset; unsignedlong c_num; //每個slab中的對象數 unsignedlong c_magic; unsignedlong c_inuse; //keptatzero kmem_slab_t *c_firstp; //第一個slab kmem_slab_t *c_lastp; //最后一個slab spinlock_t c_spinlock; unsignedlong c_growing; //是否正在增長 unsignedlong c_dflags; size_t c_org_size; //對象原始大小 unsignedlong c_gfporder; //表示slab大小的指數 void(*c_ctor)(void,kmem_cache_t,unsignedlong); //構造函數 void(*c_dtor)(void,kmem_cache_t,unsignedlong); //析構函數 unsignedlong c_align; //對象對齊關系 size_t c_colour; //cache著色區的大小 size_t c_colour_next; //著色區中下一個可用的位置 unsignedlong c_failures; constchar *c_name; //cache名 structkmem_cache_s*c_nextp; //下一個cache結構 kmem_cache_t *c_index_cachep; //分配slab->s_index數組的cache};4.2內核內存管理器(cache結構)該結構描述了一個cache的所有信息,如:一個slab的大小(占多少物理頁):c_gfporder;slab中一個對象的大小:c_org_size;一個slab可以劃分成多少對象:c_num;該cache所管理的第一個slab、最后一個slab和第一個有空閑對象的slab:c_firstp、c_lastp、c_freep;著色區:剩余空間,用于均勻分布slab對象。域c_offset的意義隨slab對象的大小而變化:對小對象:它是從對象起始地址到對象指針kmem_bufctl_s之間的距離;對大對象:它是對象的大小。4.2內核內存管理器(slab結構)#define SLAB_OFFSET_BITS 16 typedefstructkmem_slab_s{ structkmem_bufctl_s *s_freep; //第一個空閑對象 structkmem_bufctl_s *s_index; //大對象指針數組 unsignedlong s_magic; unsignedlong s_inuse; //已用的對象數 structkmem_slab_s *s_nextp; structkmem_slab_s *s_prevp; void *s_mem; //第一個對象的地址 unsignedlong s_offset:SLAB_OFFSET_BITS, s_dma:1; //能否用做DMA}kmem_slab_t;4.2內核內存管理器(slab結構)結構kmem_slab_s描述了一個slab的所有信息,如:第一個對象的地址:s_mem;指向第一個空閑對象的指針:s_freep;slab中已經用掉的對象數:s_inuse;對象可否用于DMA等。slab結構所在的位置與對象大小有關:小對象(<512字節):與對象在同一個物理頁塊上;大對象(≥512字節):在物理頁塊之外。目的是盡可能地減少內存的浪費。專門定義一個slabcache,用于管理slab結構的分配和回收。4.2內核內存管理器(slab結構)每一個小對象的尾部都加了一個kmem_bufctl_s結構,用于管理小對象。typedefstructkmem_bufctl_s{ union{ structkmem_bufctl_s *buf_nextp; kmem_slab_t *buf_slabp; void *buf_objp; }u;}kmem_bufctl_t;kmem_bufctl_s結構可以用作不同目的,如分配前用它將slab對象連接成鏈表,分配后用它指向對象所屬的slab結構等。2.4以后,該結構已經退化成一個無符號小整數。4.2內核內存管理器(通用cache)系統初始化時,預定義了14個通用cache,并已將它們的cache結構保存在數組cache_sizes[]中。typedefstructcache_sizes{ size_t cs_size; kmem_cache_t *cs_cachep;}cache_sizes_t;cache_sizes_tcache_sizes[14];32641282565121024204840968192163843276865536131072cachecachecachecachecachecache_sizes[]4.2.2cache的建立kmem_cache_t*kmem_cache_create(constchar*name, size_tsize,size_toffset,unsignedlongflags, void(*ctor)(void*,kmem_cache_t*,unsignedlong), void(*dtor)(void*,kmem_cache_t*,unsignedlong))完成如下工作:1、檢查各參數的合法性。

2、從cache_cache中申請一個內存塊用于建立新cache的kmem_cache_s結構。

3、計算并填寫新cache結構的各個域。4、將新cache的結構插入系統中的cache鏈表中。4.2.3為cache增加slabintkmem_cache_grow(kmem_cache_t*cachep,intflags)完成如下工作:1、從物理內存管理器中申請物理頁,頁數由cache結構中的c_gfporder域指定。2、建立slab結構:小對象,在物理頁的尾部(或首部)建立slab結構;大對象,在cache_slabp中申請一個slab結構。3、對大對象cache,再申請一塊內存用于建立slab對象鏈表(kmem_bufctl_t結構數組)。slab的s_index域指向該結構數組。4.2.3為cache增加slab4、修改申請到的各物理頁(不僅是第一頁)的page結構:next指向kmem_cache_s結構,prev指向kmem_slab_s結構(便于對象的釋放);在域flags上加入PG_Slab標志。5、初始化slab結構及各slab對象。小對象:將各slab對象串成鏈表,讓s_freep指向表頭。大對象:將結構數組s_index的各元素串成鏈表,讓s_freep指向表頭。6、將新slab加入cachep中,同時調整cachep的c_freep、c_firstp、c_lastp指針。4.2.3為cache增加slabslab結構s_indexs_freeps_memkmem_bufctl_t結構數組大對象cache的slab結構物理頁塊對象對象對象對象4.2.3為cache增加slabs_freepkmem_bufctl_t著色區Slab結構……小對象cache的slab結構

小對象小對象小對象4.2.4對象的分配有兩種對象分配函數:kmalloc(size_tsize,intflags)kmem_cache_alloc(kmem_cache_t*cachep,intflags)當只知大小不知cache時用第一個,知道cache時用第二個。kmalloc先根據size在cache_sizes[]中找到一個通用cache,而后再從cache中分配對象。從cache中分配對象的方法如下:1、如果還未為cache創建slab,或它的所有slab都沒有空閑對象,則調用函數kmem_cache_grow()為其創建一個新的slab。4.2.4對象的分配2、找出該cache中有空閑對象的第一個slab,并找到它的第一個空閑對象(s_freep)。將第一個空閑對象分配出去(bufp),并調整slab的參數。3、返回空閑對象的首地址: 1)小對象: objp=((void*)bufp)-cachep->c_offset; //地址 bufp->buf_slabp=slabp; //指向它所屬的slab 2)大對象: objp=((bufp-slabp->s_index)*cachep->c_offset) +slabp->s_mem; bufp->buf_objp=objp;4.2.5對象的釋放三種釋放操作:1、知道對象所屬cache時,用:kmem_cache_free(kmem_cache_t*cachep,void*objp)2、不知對象所屬cache時,用:kfree(constvoid*objp)1)mem_map[objp>>12]是objp所在物理頁的page2)(kmem_cache_t*)(>next)是該頁對應的cache結構3、知道對象大小時,用:kfree_s(constvoid*objp,size_tsize)增加一個大小檢查。4.2.5對象的釋放(小對象)1、利用對象尾部的指針找到它所屬的slab。 bufp=(kmem_bufctl_t*)(objp+cachep->c_offset); slabp=bufp->buf_slabp;2、將對象加入slab的空閑對象隊列中。3、調整cache的空閑隊列:1)如果釋放以后slab全部空閑,將該slab移到slab隊列的隊尾,以便歸還給物理內存管理器。2)如果釋放以前slab已被全部分完,則將該slab后移,以保證slab隊列的順序,必要時調整cache的c_freep指針。4.2.5對象的釋放(大對象)1、根據對象地址objp,找到對象所在的物理頁,并據此找到該對象所屬的slab:slabp=(kmem_slab_t*)(mem_map[objp>>12].prev);2、算出該對象在指針數組中的位置:slabp->s_index[(objp-slabp->s_mem)/cachep->c_offset]3、將對象加入slab的空閑對象隊列中。1)如果釋放以后slab全部空閑,則將該slab移到隊尾。2)如果釋放以前slab已被全部分完,則將該slab后移,必要時調整cache的c_freep指針。4.2.6回收cache中的空閑slab函數kmem_cache_reap按照時鐘算法,每次搜索10個cache,從中選擇一個空閑slab最多的cache,將它的空閑slab歸還給物理內存管理器。

1、從clock_searchp開始順序搜索各cache,找出一個空閑slab最多的cache。

2、調整clock_searchp,使其指向找到的cache。3、回收該cache的空閑slab。下列cache不在回收之列:標志為SLAB_NO_REAP的cache正在增長的cache已經損壞的cache不滿足要求的cache4.3虛擬內存管理器直接使用物理內存管理器可以運行程序,方法是:申請足夠的內存,將程序一次性全部裝入。但可能帶來如下問題:1、當程序過大時(超過可用的物理內存量),無法將其裝入內存,因而無法運行。2、多進程并發執行的開銷很大(需要將進程整個或部分地換出/換入內存)。3、由于直接使用物理內存,因而進程之間難以實現隔離和保護。4、程序的設計依賴于物理內存的配置,編程困難且程序難以移植。4.3虛擬內存管理器但大程序、多進程、并發、保護、移植等是現代軟件設計不可回避的問題,因而是操作系統必須解決的問題。人們提出了很多方法來解決上述問題,如覆蓋、交換,但這兩種技術都不能完全滿足需要。軟件覆蓋技術:通過覆蓋那些暫時不用的程序代碼或數據來復用內存。

交換機制:進程被作為一個完整的單位,在內存和外存之間交換。4.3虛擬內存管理器為此又提出了基于分頁機制的虛擬內存管理,其思路是:虛擬(欺騙),即給用戶進程造成系統有大內存,而且它獨占大內存的假象。方法:1、隔離:不讓用戶進程看到實際的物理內存,只給它看到一個美好的假象(虛擬內存)。2、勤快:頻繁地在內、外存之間移動數據,保證進程當前使用到的代碼和數據在內存中。3、小單位:量小、速度快,不易被察覺。規律:程序運行的局部性規律。4.3虛擬內存管理器1978年,Unix系統在VAX機上第一次實現了基于分頁機制的虛擬內存管理器:1、將物理地址空間和程序的虛擬地址空間都分成固定大小的頁,同時引入頁表,實現虛擬空間與物理空間的隔離,并負責虛擬地址到物理地址的轉換。2、地址的轉換由硬件實現,轉換所用的頁表由操作系統內核維護。3、虛擬內存管理器負責在內外存之間交換頁面,給用戶造成假象,使得每個進程都認為自己是系統中唯一的一個程序,獨占系統的全部地址空間(4GB)。分頁機制、頁表、虛擬內存的引入,是操作系統發展史上一個里程碑。4.3虛擬內存管理器OS程序邏輯地址空間物理地址空間頁表交換外存搬入搬出搬入4.3虛擬內存管理器虛擬內存管理器的優點(設計目標):1、大地址空間:進程可用的地址空間可超過物理內存總量。2、并發:允許多進程同時駐留內存。3、進程保護:不同進程的虛擬地址空間完全隔離。4、虛存共享:不同進程之間可以共享物理頁。5、代碼可移植:在設計程序時不必預先約定機器的配置。6、內存映射:將文件映射到進程的虛擬地址空間,使得對文件的訪問與對內存單元的訪問一樣。7、允許程序重定位:程序可以放在物理內存中的任意位置,且可以在執行過程中任意移動。8、代價小:換入換出單個頁面的代價比交換整個進程或內存段要小得多。4.3虛擬內存管理器虛擬內存管理器的功能:1、地址空間管理:負責進程虛擬地址空間的創建、回收和動態改變。2、地址轉換:將進程產生的虛擬地址轉換為物理地址。當無法轉換時,產生缺頁異常。(硬件和內核共同完成)3、缺頁處理:當產生缺頁異常時,把需要的頁面裝入內存。4、換出:當物理內存緊缺時,將進程的某些頁面換出內存。5、內存保護:以頁為單位實現內存的保護。當發現非法地址訪問時,向進程發送段違例信號(SIGSEGV)。6、內存共享:允許別的進程共享其地址空間的某一部分。7、監視系統負荷:當系統超負荷時,采取相應措施,如停止啟動新進程等。8、其它服務:提供對其它功能的支持,如文件映射、動態連接庫等。4.3虛擬內存管理器幾個概念: 裝入 執行程序地址 進程地址 機器地址 描述符 頁表邏輯地址 線性地址 物理地址

(虛擬地址)

邏輯地址空間 線性地址空間 物理地址空間

(虛擬地址空間)4.3.1虛擬內存抽象模型(頁表)在虛擬內存管理結構中,頁表是最關鍵、最基本的數據結構。在Intel處理器中分為兩級:頁目錄、頁表,以下統稱為頁表。頁表是頁表項的數組,具有以下特征:1、頁表的內容只能由內核改變,進程無法看到、更無法修改自己的頁表。2、頁表項具有非常豐富的含義。當頁在內存時,頁表項記錄映射關系和控制信息。當頁不在內存時,頁表項記錄頁面在外存中的位置。頁表項中包含有豐富的控制信息,可以實現對頁的管理和保護。4.3.1虛擬內存抽象模型(頁表)3、頁表及其內容可以動態變化。頁表項甚至頁表本身都可以動態地創建、修改、刪除、切換,以反映映射關系的變化。所有這些改變均由內核完成,對用戶透明。4、頁表項的內容不受限制。映射關系可動態變化。映射順序沒有要求,不需要連續,也不需要有序。可以重疊,即可以將多個進程的虛擬頁映射到同一個物理頁(共享)。5、通過頁表可以實現進程虛擬地址空間的隔離。每個進程都有自己的頁目錄和頁表,一個進程不能使用別的進程的頁表。進程切換時,其頁目錄要同時切換。4.3.1虛擬內存抽象模型(頁表)由于虛擬空間很大,所以頁表也很大。如4GB的虛擬地址空間有1024*1024個頁表項。采用一級頁表浪費空間,管理也不方便。所以,通常建立多級頁表。為了統一起見,Linux采用三級頁表。在Intel處理器中,第一級頁表對應頁目錄,第二級頁表稱為頁中間表(目錄),第三級頁表對應為處理器的頁表。每個頁目錄中有1024個頁目錄項,每個頁目錄項描述一個頁中間表;每個頁中間表只有1個頁中間項,每個頁中間項描述一個頁表;每個頁表有1024個頁表項,每個頁表項描述一個虛擬頁。4.3.1虛擬內存抽象模型(頁表)頁目錄和頁表描述了進程的整個虛擬地址空間。頁表項可以為空,頁目錄項也可以為空。如果頁目錄項為空,它對應的整個頁表都不存在。事實上,進程的頁表是在使用的過程中動態建立的。因此,進程的頁表實際占用的空間要遠遠小于4MB。頁目錄和頁表是虛擬內存管理的重要數據結構,虛擬內存管理器通過不斷地調整頁目錄和頁表項來管理進程的虛擬地址空間。4.3.1虛擬內存抽象模型(VMA)進程的所有信息,包括代碼、數據、堆棧、共享區等,都存放在它的虛擬地址空間中。由于屬性的不同,進程對自己虛擬地址空間的使用方式也不同,因此對它們的管理方式也應該不同。如程序代碼可以執行但不能修改,數據部分可以讀寫但不能執行,堆棧可以動態地增長等。因此,應該根據進程的具體情況,將它的虛擬地址空間劃分成小的虛擬內存區域(區間)。每個虛擬內存區域就是一段具有相同屬性的、連續的虛擬地址空間。虛擬內存區域可大可小,最小一頁,最大不超過4GB。4.3.1虛擬內存抽象模型(VMA)structvm_area_struct{ structmm_struct *vm_mm; unsignedlong vm_start; unsignedlong vm_end; structvm_area_struct *vm_next; pgprot_t vm_page_prot; unsignedshort vm_flags; short vm_avl_height; //AVL樹 structvm_area_struct *vm_avl_left; structvm_area_struct *vm_avl_right; structvm_area_struct *vm_next_share;//用于映射頁和共享頁 structvm_area_struct **vm_pprev_share; structvm_operations_struct*vm_ops; unsignedlong vm_offset; structfile *vm_file; unsignedlong vm_pte; //共享內存專用};4.3.1虛擬內存抽象模型(VMA)structvm_operations_struct{ void(*open)(structvm_area_struct*area); void(*close)(structvm_area_struct*area); void(*unmap)(structvm_area_struct*area,unsignedlong,size_t); void(*protect)(structvm_area_struct*area,unsignedlong, size_t,unsignedintnewprot); int(*sync)(structvm_area_struct*area,unsignedlong, size_t,unsignedintflags); void(*advise)(structvm_area_struct*area,unsignedlong, size_t,unsignedintadvise); unsignedlong(*nopage)(structvm_area_struct*area, unsignedlongaddress,intwrite_access); unsignedlong(*wppage)(structvm_area_struct*area, unsignedlongaddress,unsignedlongpage); int(*swapout)(structvm_area_struct*,structpage*); pte_t(*swapin)(structvm_area_struct*,unsignedlong, unsignedlong);};4.3.1虛擬內存抽象模型(VMA)vm_endvm_startvm_flagsvm_opsvm_offsetvm_filevm_nextvm_area_struct進程的虛擬內存opencloseunmapprotectsyncadvisenopagewppageswapoutswapin文件虛擬內存區域用來彌補頁表項的不足。4.3.1虛擬內存抽象模型(MM)一個進程會有很多虛擬內存區域,虛擬內存管理器經常需要使用這些虛擬內存區域。如,當發生缺頁異常時,要根據發生異常的虛擬地址,找到包含它的虛擬內存區域,從而決定具體的處理方式。因此需要一種機制來管理一個進程的所有vma結構。另外,虛擬內存管理器還需要一個結構來記錄進程中與內存有關的信息。如進程頁目錄的位置,進程的代碼、數據、堆棧、堆、參數、環境變量等在虛擬空間中的位置,進程駐留在物理內存中的頁面個數,進程的LDT等。

為每個進程建立一個內存管理結構mm_struct。4.3.1虛擬內存抽象模型(MM)structmm_struct{ structvm_area_struct*mmap; //vma鏈表 structvm_area_struct*mmap_avl; //vma樹 structvm_area_struct*mmap_cache; //最后一次使用的vma pgd_t *pgd; //進程的頁目錄 atomic_t count; //引用計數 int map_count; //VMAs個數 structsemaphore mmap_sem; unsignedlong context; unsignedlong start_code,end_code,start_data,end_data; unsignedlong start_brk,brk,start_stack; unsignedlong arg_start,arg_end,env_start,env_end; unsignedlong rss,total_vm,locked_vm; unsignedlong def_flags; unsignedlong cpu_vm_mask; unsignedlong swap_cnt; //可以換出的頁數 unsignedlong swap_address; void *segments; //進程的LDT};4.3.1虛擬內存抽象模型(MM)

mmappgdvm_endvm_startvm_offsetvm_endvm_startvm_offsetvm_endvm_startvm_offsetmm_structvm_area_struct虛擬內存區域1區域3區域2數據數據程序可執行文件004.3.1虛擬內存抽象模型訪問控制

每個vma中都包含有一個vm_page_prot域,其中記錄了缺省情況下對該區域的所有頁的保護權限設置。

真正對頁起到保護作用的是定義在各個頁表項中的訪問控制信息,對頁表項中訪問控制信息的設置要參考vma中的域vm_page_prot。

當處理器轉換虛擬地址時,它利用頁表項中的控制信息檢查進程對頁的訪問,防止進程非法使用內存。

限制對于內存區域的訪問會提高系統的安全性。4.3.1虛擬內存抽象模型按需調頁(DemandPaging)節省物理內存的一種方法是只加載進程當前正在使用的虛擬頁。這種直到訪問時才加載虛擬頁的技術叫做按需調頁(demandpaging)。由于按需調頁,虛擬內存管理器必須處理pagefault異常。使用按需調頁技術可以實現內存映射,即將文件的內容映射到進程的虛擬內存。4.3.1虛擬內存抽象模型交換(Swapping)

物理內存回收程序可能會回收進程的頁,包括廢棄和換出。如果需要回收的頁來自磁盤上的映像或者數據文件,而且頁沒有被修改過,則可以直接將其廢棄。如果需要回收的頁已經被修改過,則必須保留它的內容以便恢復。保存到映像文件中保存到交換設備中虛擬內存管理器必須仔細地處理頁的交換。有效的交換方案應該保證所有進程的工作集(workingset)都在物理內存中。4.3.1虛擬內存抽象模型高速緩存(Caches):1、BufferCache2、PageCache

3、SwapCache

4、HardwareCache:TLB(TranslationLookasideBuffers)4.3.1虛擬內存抽象模型虛擬空間變化

1、在進程創建時,從父進程拷貝虛擬地址空間。

2、在進程需要裝入新的執行映像時,根據執行映像的定義,重建它的內存管理結構,從而重建進程虛擬地址空間。3、缺頁異常處理程序會將頁讀入內存,修改頁表。4、物理內存回收程序會將暫時不用的頁從內存中換出,修改頁表。5、在進程結束時,釋放它在內存中的所有頁和它的所有內存管理結構,從而釋放它的虛擬地址空間。4.3.2虛擬內存拷貝進程創建時要拷貝父進程的虛擬地址空間。好處是父子進程可以完成同樣的工作(如Server),壞處是代價太高。解決的方法是:1、vfork:父進程將自己的地址空間借給子進程然后睡眠,直到子進程重建自己的虛擬地址空間或exit退出。2、Copyonwrite:父子進程有自己獨立的虛存管理結構和頁目錄、頁表,且頁表項的內容相同,但各頁都被設置為只讀。如果父或子進程要修改某頁,系統會產生保護異常。異常處理程序識別出這種情況后,為修改頁面的進程創建一個副本。如果沒有修改頁面的動作,父子進程就會一直共享同一個頁面,不需要拷貝。

Linux同時支持上述兩種改進。4.3.2虛擬內存拷貝(一)inlineintcopy_mm(intnr,unsignedlongclone_flags,structtask_struct*tsk)

1、如果標志clone_flags中設置了CLONE_VM,則將父進程內存結構的引用記數加1,返回0。2、否則,要拷貝內存結構:1)申請一個mm_struct結構mm,將父進程mm_struct結構的內容拷貝到mm:*mm=*current->mm;

2)調整mm的部分內容,如mmap、引用計數等。3)為新進程建立頁目錄:用戶部分(前0x300)清0,內核部分(后0x100)從init_task的頁目錄中拷貝。4)將新頁目錄的地址寫入新進程TSS段和mm->pgd中。5)將父進程的所有虛擬內存區域都拷貝到新進程中來:dup_mmap(mm);4.3.2虛擬內存拷貝(二)inlineintdup_mmap(structmm_struct*mm)1、順序搜索父進程的vma鏈表,對其中的每個vma結構mpnt做如下處理:1)從內核內存管理器申請一個vm_area_struct結構tmp,并將mpnt的內容拷貝到tmp中:*tmp=*mpnt;2)調整tmp的某些域,如vm_flags、vm_mm等。3)如果mpnt是一個文件映射區域,則將vm_file的引用計數加1,并將tmp加入文件inode結構的vma鏈表中。4)copy_page_range(mm,current->mm,tmp);拷貝mpnt對應的頁目錄、頁表項:5)如果tmp的操作集中定義有open操作,則執行它。6)將tmp加入內存管理結構mm的vma隊列中。2、如果新進程的內存區域總數大于32,則為其建立AVL樹,以加快查找速度。4.3.2虛擬內存拷貝(三)intcopy_page_range(structmm_struct*dst,structmm_struct*src,structvm_area_struct*vma)按照vma的開始和終止地址,找出它們在新、老頁目錄中的位置。順序拷貝各頁目錄項:1、拷貝目錄項:1)如果老目錄項為空,則不需要拷貝;2)如果老目錄項有錯,則將其清0;3)如果新目錄項為空,則創建一個新頁表。2、找到vma在新、老頁表中的位置,順序拷貝各頁表項:1)如果老頁表項為空,則不需要拷貝;2)如果老頁表項所指的頁不在內存,則拷貝它,而后修改該頁在交換設備中的引用計數;3)如果老頁表項為保留頁,則拷貝;4)如果老頁表項是copyonwrite頁,則將老頁表項改為只讀,拷貝;5)其余情況,清除老頁表項中的存取標志,拷貝。4.3.3虛擬內存重建當進程希望改變自己的行為時,它可以調用函數exec,根據新的執行映像重建自己的虛擬地址空間(映像文件的裝入)。Linux采用內存映射機制裝入執行映像。實際是根據執行映像文件建立一組vm_area_struct結構。1、系統調用exec完成執行映像的加載。2、系統調用old_mmap或sys_mmap可以為數據文件建立虛擬映射區域。函數do_mmap用于建立一個虛擬內存區域。4.3.3虛擬內存重建函數do_mmap建立的內存映射區域有兩種:1、共享區域的頁允許多個進程共享,它在內存中只有一份拷貝,進程可以直接修改共享映射區域的頁。當需要將共享映射頁從內存換出時,系統會將修改過的共享映射頁直接寫回到映射文件。2、私有區域的頁是進程專有的,多個進程可以同時讀它,但當某進程試圖寫時,系統會為寫進程創建一個副本,進程對私有映射頁的寫操作都在自己的副本上進行。當要將私有映射頁換出內存時,系統會將其寫入交換設備,而不是映射文件。共享區域和私有區域的換出操作不同。4.3.3虛擬內存重建unsignedlongdo_mmap(structfile*file,unsignedlongaddr,unsignedlonglen,unsignedlongprot,unsignedlongflags,unsignedlongoff)do_mmap完成如下工作:1、檢查各參數的合法性。2、找出映射區域的開始地址(可能不同于addr)。3、申請一個vm_area_struct結構,并根據參數填寫它。4、如果file不空,則執行其上的mmap操作(設置操作集)。5、將vma插入mm_struct中,如果必要,建立vma的avl樹。

6、如果file不空,則將vma插入到文件inode的i_mmap隊列中。7、如果可能,合并兩個相臨的內存區域。8、累計進程虛擬內存的總量,返回映射區域的開始地址。4.3.4缺頁處理當CPU訪問到以下進程頁時,會產生pagefault異常:1、不在內存中的進程頁;2、違反了保護約定的進程頁。操作系統處理pagefault異常的一般過程是:1、找到發生異常的虛擬地址。2、根據虛擬地址查找包含它的虛擬內存區域vma。如果找不到這樣的vma,或訪問方式確實違反了vma的保護約定,則向進程發送SIGSEGV信號。3、找到異常頁對應的頁表項。根據頁表項的內容、虛擬內存區域vma的內容和異常錯誤代碼,決定如何處理異常。處理的方法包括:從映射文件上讀入頁,從交換設備上讀入頁,復制Copyonwrite頁,建立匿名頁等。4.3.4缺頁處理當缺頁異常發生時,處理器在系統堆棧上壓入一個錯誤代碼(error_code)。錯誤代碼的意義如下:代碼位

意義

第0位P位0:引起異常的頁不在內存1:引起異常的頁在內存第1位W/R位0:引起異常的操作是讀1:引起異常的操作是寫第2位U/S位0:異常發生時,處理器在超級用戶模式1:異常發生時,處理器在普通用戶模式4.3.4缺頁處理缺頁處理函數是do_page_fault,定義如下:asmlinkagevoiddo_page_fault(structpt_regs*regs,unsignedlongerror_code)

它有兩個參數:指向pt_regs結構的指針和error_code。缺頁異常的處理過程如下:1、找到當前進程的內存管理結構mm。2、找到發生異常的地址address(CR2寄存器)。4.3.4缺頁處理3、檢查,看address是否在某vma中。找vm_end比address大的第一個vm_area_struct結構vma。結果如下:1)找不到,轉bad_area。2)address在vma內,轉good_area。3)address在vma之下但vma不能或無法向下擴展,轉bad_area。4)address在vma之下且vma能向下擴展(用戶堆棧),則將其向下擴展至少1頁。轉good_area。4.3.4缺頁處理4、good_area:根據異常錯誤碼決定處理方法:1)讀一個不存在的頁:如vma不允許讀或執行,轉bad_area;否則,轉5。2)讀一個存在的頁:該頁肯定不可讀,因此出錯,轉bad_area。3)寫一個不存在的頁:如vma不允許寫,轉bad_area;否則,轉5。4)寫一個存在的頁:如vma不允許寫,轉bad_area;否則,說明要寫的是一個copyonwrite頁,轉5。5、正常缺頁處理handle_mm_fault()。如成功,則正常返回;否則,轉do_sigbus。4.3.4缺頁處理6、bad_area:1)如果異常發生時,處理器在用戶模式,則向當前進程發送一個SIGSEGV信號,告訴進程出現段或頁違例,返回。通常情況下,該信號會導致進程自殺。2)如果是CPU缺陷引起的異常,則修正它,返回。7、do_sigbus:1)給進程發送一個SIGBUS信號;2)如果發生異常時,處理器在用戶態,則返回;否則,轉no_context。8、no_context:1)內核錯誤。如果能修復則修復,返回。2)如果是對MMU寫保護功能的測試,則設置參數,返回。3)壞頁且無法修復。顯示信息,終止整個系統的運行。4.3.4缺頁處理函數handle_mm_fault()的處理如下:1、找出address對應的頁目錄項。如果頁目錄項有錯(保護標志錯),則將其標記為BAD_PAGETABLE,此次缺頁處理失敗,返回0。2、找出address對應的頁表項:1)如果頁表不存在(頁目錄項的值為0),則創建一個新的頁表。2)根據address的第12到21位找到頁表項。調用函數handle_pte_fault()處理單個頁表項(單個虛擬頁)的異常。如果成功,返回1;否則,返回0。4.3.4缺頁處理函數handle_pte_fault()的處理過程如下:分析頁表項的內容,找出頁的位置。有如下情況:1、頁不在內存(p位為0),則:1)如頁表項為0,說明頁在映射文件中。從映射文件中讀入它:如果vma上沒有操作集,或其操作集中沒有nopage操作,則vma是匿名區域(不對應任何文件)。處理匿名頁:do_anonymous_page()。調用vma操作集中的nopage操作,從映射文件或關系內存中讀入頁:filemap_nopage()、shm_nopage()。2)如頁表項不為0,說明它在交換設備上。從交換設備上讀入頁:do_swap_page()。4.3.4缺頁處理2、頁在內存,則:1)如果發生異常的動作是寫,且vma允許寫而頁不允許寫,則該頁是一個copyonwrite頁。為該頁創建一個拷貝:

do_wp_page(tsk,vma,address,pte);2)如果發生異常的動作是寫,且vma和頁都允許寫,則將頁表項上臟頁位設置為1、填入頁表、刷新TLB。3)如果發生異常的動作是讀,則將頁表項上存取位置1,填入頁表,刷新TLB表。4.3.4缺頁處理歸結起來,對缺頁的處理過程如下:do_page_fault

handle_mm_fault handle_pte_faultdo_swap_page do_no_page do_wp_pagedo_anonymous_page

filemap_nopage shm_nopage 對缺頁處理的方法有五種: 處理匿名頁:do_anonymous_page

處理映射文件頁:filemap_nopage

處理共享內存頁:shm_nopage 處理交換設備頁:do_swap_page 處理Copyonwrite頁:do_wp_page4.3.4缺頁處理intdo_anonymous_page(structtask_struct*tsk,structvm_area_struct*vma,pte_t*page_table,intwrite_access)1、匿名頁都映射到empty_zero_page,該頁不能寫:1)如果引起異常的動作是讀,則根據empty_zero_page的地址和vma的保護信息創建一個頁表項,清除其中的_PAGE_RW標志,將該頁設置為copyonwrite頁。2)如果引起異常的動作是寫,則:向物理內存管理器申請一個新頁并將其清0。用新頁的地址和vma的保護信息創建一個頁表項,并在其中設置上_PAGE_DIRTY和_PAGE_RW標志。2、將創建好的頁表項填入頁表。

3、成功,返回1。4.3.4缺頁處理unsignedlongfilemap_nopage(structvm_area_struct*area, unsignedlongaddress,intno_share)1、根據area找到文件,根據address算出頁在文件中的偏移量offset。2、根據文件的inode和offset查找頁緩存:1)頁不在緩存中:申請物理頁,將其加入頁緩存,調用inode上的readpage操作讀入該頁的內容。此處可能一次讀入多頁。2)頁在緩存但正被鎖定(正在做I/O):等待。3)頁在緩存中但不是最新的:調用inode上的readpage操作讀入該頁。4)頁在緩存中且是最新的:如果area是共享的,則可以直接使用它。返回頁的開始地址。如果area是私有的,但引起異常的動作是讀,則可以直接使用它(設為寫保護)。返回該頁的開始地址。如果area是私有的,且引起異常的動作是寫,則創建頁的一個副本。返回副本的開始地址。

5)如果上述任何一處出錯,則返回0,表示失敗。4.3.4缺頁處理共享內存是進程間的一種通信機制,它允許多個進程通過共享內存頁互相通信。由于一塊共享內存對應的物理頁可以出現在多個進程的頁表中,因此對共享內存缺頁的處理有些特別的地方。因為處理共享內存的缺頁需要了解共享內存機制,因此,將把對函數shm_nopage的討論推遲到第六章。4.3.4缺頁處理intdo_swap_page(structtask_struct*tsk,structvm_area_struct*vma, unsignedlongaddress,pte_t*page_table,pte_tentry,intwrite_access)1、如果vma中沒有定義swapin操作,則調用缺省的換入函數: swap_in(tsk,vma,page_table,pte_val(entry),write_access);目前的所有虛擬內存區域中都沒有定義換入函數。swap_in的定義在交換一節中討論。2、返回1,表示成功。4.3.4缺頁處理intdo_wp_page(structtask_struct*tsk,structvm_area_struct*vma, unsignedlongaddress,pte_t*page_table)1、如果頁本來就不在內存或已經允許寫,則返回1。2、如果老物理頁不存在,則向進程發送SIGKILL信號,錯誤返回0。3、下列情況不需要拷貝物理頁:1)如果老物理頁的唯一一個用戶是當前進程;2)如果老物理頁只有兩個用戶(當前進程和交換緩存),而且沒有別的進程引用該交換頁,則將其從交換緩存中刪除。 將頁置成可寫、臟頁,刷新頁表,返回1。4、如果頁有多個用戶,則需要拷貝:1)申請一個物理頁,將老頁的內容拷貝到新頁中。2)根據新頁的物理地址和vma的保護權限構造一個頁表項,在其中增加可寫、臟頁標志,將其填入頁表中。3)釋放對老頁的引用,刷新TLB表,成功返回1。4.3.7頁緩存從文件中讀入頁需要經過頁緩存。使用頁緩存(pagecache)的目的是:減少讀文件的次數,加快對文件的訪問速度。從文件系統中讀入的每一頁(缺頁時讀入的頁和用read操作讀入的頁)都被緩存在頁緩存中。頁緩存中的頁包括共享映射頁和私有映射頁的主本,私有映射頁的副本不在頁緩存中。頁緩存是一個Hash表。structpage*page_hash_table[4096];

以VFSinode和文件中的偏移量為索引,來確定一個文件頁在頁緩存中的位置。4.3.7頁緩存page_hash_tablepagepagepagepagepage……Page結構中的next_hash和pprev_hash指針用于將物理頁加入頁緩存4.3.7頁緩存1、當需要從文件中讀入頁時,系統首先根據文件的VFSinode和頁在文件中的偏移量查頁緩存。如果需要的頁在頁緩存中,而且其內容是最新的,就可以立刻使用它,從而可以避免一次I/O操作。只有當要讀入的頁不在頁緩存或雖在頁緩存但內容不是最新的時,才需要將其從文件中讀入。新讀入的頁也被加入頁緩存。通常情況下,Linux會啟動超前讀,即一次將多個文件頁讀入到內存,并加入到頁緩存。4.3.7頁緩存2、當需要回收物理內存時,回收程序會搜索頁緩存,找無進程引用的頁(引用計數為1):如頁是干凈的,可以直接將其廢棄、回收。如頁是臟的,可以先將其寫回文件、再回收。共享映射頁的回收是一種典型的情況。vm_endvm_startvm_flagsvm_opsvm_offsetvm_filevm_nextvm_area_struct虛擬內存文件4.3.5共享映射頁的回收共享映射區域中的頁是和映射文件直接對應的,其內容來源于文件,進程可以直接修改共享映射頁。映射文件是共享映射頁的備份。當需要回收共享映射頁時:如頁未修改過,可以直接將其收回;如頁被修改過(臟的),可以先將其寫回映射文件,而后再將其收回。在兩種情況下,共享映射頁會寫回映射文件:1、物理內存回收程序在回收被修改過(臟頁)的共享映射頁時;2、內核守護進程kpiod活動時。4.3.5共享映射頁的回收滿足以下條件的共享映射頁需要在回收前寫出(淘汰):1、在進程的虛擬地址空間中,即該頁必須出現在進程的某個虛擬內存區域vma中。2、在內存,即它的頁表項的存在位為1。3、最近未被存取過,即它的頁表項中的A位為0。4、不是內核保留頁。5、頁上沒有加鎖,即在該頁上沒有正在進行的I/O操作。6、不在交換緩存中。7、是臟頁(不臟的頁可以直接廢棄,不需要寫出)。8、是共享映射頁。4.3.5共享映射頁的回收回收程序try_to_swap_out對共享映射頁做如下工作:1、找到頁表項和page結構。如果頁表項的A位為1,則將其清0,將page中的PG_referenced置1。返回。2、將共享映射頁在進程頁表中的頁表項清0。3、使共享映射頁在TLB中失效。4、vma->vm_mm->rss--; //駐留內存的頁數5、調用文件操作集上的寫操作(vma->vm_file->f_op->write()),將page的內容寫到文件的offset處。6、釋放物理頁:__free_page(page_map);4.3.5共享映射頁的回收共享映射頁同時出現在頁緩存和進程頁表中,因此該物理頁的引用計數至少是2。函數__free_page()僅僅將它的引用計數減1,并不能真正釋放它,物理頁仍然在頁緩存中。共享映射頁頁表物理內存頁緩存4.3.5共享映射頁的回收如果函數__free_page()執行后,物理頁的引用計數大于1,說明還有別的進程引用它,該頁不會被回收。如果物理頁的引用計數為1,則在下一次回收物理內存時,函數shrink_mmap()會檢查它的PG_referenced標志:如該標志為1,則將其清0,返回;否則,將它從頁緩存中刪除,從而真正將其回收。如果在頁被真正回收之前,又有進程(包括釋放該共享映射頁的進程)訪問了該頁,則缺頁處理程序會直接從頁緩存中查到該頁,從而又會將其加入到進程的頁表,其引用計數就又會大于1,這樣以來,物理內存回收程序就不會真正將其回收。4.3.5共享映射頁的回收這就是Linux采用的二次機會淘汰算法,是一種“lazy”的處理方法。將共享頁從進程的虛擬地址空間寫出,但不立刻將其從頁緩存中釋放,有下列好處:1、如果該頁很快又被訪問,可以避免一次讀盤操作,從而可以提高系統的性能,也可以減少因淘汰失誤而造成的影響。2、如果到下次回收物理內存時,該頁仍沒有被訪問,則根據局部訪問原則,該頁很快被訪問的可能性就較小,因此可以放心地將其回收。4.3.6交換如果需要回收的頁是私有映射頁的副本,則不應該將它直接寫回映射文件,只能將其寫到外存的某個地方暫存。如果要回收的頁不是內存映射頁,則該頁在磁盤上根本就沒有對應的文件,因此只能將其寫到外存的某個地方暫存。用于暫存換出頁面的文件叫交換文件,用于暫存換出頁面的設備叫交換設備。以下統稱為交換設備。4.3.6交換在安裝Linux系統時,一般都要求創建交換設備。交換設備可能是單獨的塊設備,也可能是磁盤設備的一個分區,當然也可以是獨立的文件。為了提高性能,系統中可以建立多個交換設備,而且可以將這些交換設備分布在不同的塊設備(如磁盤)上。交換設備上沒有建立文件系統,但它的第0頁上寫有特殊的控制信息。如下:4.3.6交換第0頁是下面形式的結構:unionswap_header{ struct{ charreserved[PAGE_SIZE-10]; //位圖 charmagic[10]; //魔數 }magic; //老版本 struct{ char boo

溫馨提示

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

評論

0/150

提交評論