




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
《深入解析Linux內(nèi)存管理》
季丹深入解析Linux內(nèi)存管理第1頁目錄預(yù)備知識頁表管理內(nèi)核頁表物理內(nèi)存高端內(nèi)存地址映射虛擬內(nèi)存地址空間高速緩存頁框回收交換機(jī)制缺頁異常共享內(nèi)存文件映射程序執(zhí)行深入解析Linux內(nèi)存管理第2頁預(yù)備知識微機(jī)原理內(nèi)存芯片AT&T匯編保護(hù)模式腳本鏈接內(nèi)核架構(gòu)深入解析Linux內(nèi)存管理第3頁頁表管理1.邏輯地址轉(zhuǎn)線性地址2.線性地址轉(zhuǎn)物理地址深入解析Linux內(nèi)存管理第4頁邏輯地址轉(zhuǎn)線性地址機(jī)器語言指令中出現(xiàn)內(nèi)存地址,都是邏輯地址,需要轉(zhuǎn)換成線性地址,再經(jīng)過MMU(CPU中內(nèi)存管理單元)轉(zhuǎn)換成物理地址才能夠被訪問到。我們寫個最簡單helloworld程序,用gccs編譯,再反編譯后會看到以下指令:mov
0x80495b0,%eax這里內(nèi)存地址0x80495b0就是一個邏輯地址,必須加上隱含DS數(shù)據(jù)段基地址,才能組成線性地址。也就是說0x80495b0是當(dāng)前任務(wù)DS數(shù)據(jù)段內(nèi)偏移。在x86保護(hù)模式下,段信息(段基線性地址、長度、權(quán)限等)即段描述符占8個字節(jié),段信息無法直接存放在段存放器中(段存放器只有2字節(jié))。Intel設(shè)計是段描述符集中存放在GDT或LDT中,而段存放器存放是段描述符在GDT或LDT內(nèi)索引值(index)。Linux中邏輯地址等于線性地址。為何這么說呢?因為Linux全部段(用戶代碼段、用戶數(shù)據(jù)段、內(nèi)核代碼段、內(nèi)核數(shù)據(jù)段)線性地址都是從0x00000000開始,長度4G,這么線性地址=邏輯地址+0x00000000,也就是說邏輯地址等于線性地址了。深入解析Linux內(nèi)存管理第5頁邏輯地址轉(zhuǎn)線性地址這么情況下Linux只用到了GDT,不論是用戶任務(wù)還是內(nèi)核任務(wù),都沒有用到LDT。GDT第12和13項段描述符是__KERNEL_CS和__KERNEL_DS,第14和15項段描述符是__USER_CS和__USER_DS。內(nèi)核任務(wù)使用__KERNEL_CS和__KERNEL_DS,全部用戶任務(wù)共用__USER_CS和__USER_DS,也就是說不需要給每個任務(wù)再單獨分配段描述符。內(nèi)核段描述符和用戶段描述符即使起始線性地址和長度都一樣,但DPL(描述符特權(quán)級)是不一樣。__KERNEL_CS和__KERNEL_DSDPL值為0(最高特權(quán)),__USER_CS和__USER_DSDPL值為3。用gdb調(diào)試程序時候,用inforeg顯示當(dāng)前存放器值:cs
0x73
115ss
0x7b
123ds
0x7b
123es
0x7b
123能夠看到ds值為0x7b,轉(zhuǎn)換成二進(jìn)制為0000000001111011,TI字段值為0,表示使用GDT,GDT索引值為01111,即十進(jìn)制15,對應(yīng)就是GDT內(nèi)__USER_DATA用戶數(shù)據(jù)段描述符。從上面能夠看到,Linux在x86分段機(jī)制上運(yùn)行,卻經(jīng)過一個巧妙方式繞開了分段。Linux主要以分頁方式實現(xiàn)內(nèi)存管理。深入解析Linux內(nèi)存管理第6頁深入解析Linux內(nèi)存管理第7頁線性地址轉(zhuǎn)物理地址前面說了Linux中邏輯地址等于線性地址,那么線性地址怎么對應(yīng)到物理地址呢?這個大家都知道,那就是經(jīng)過分頁機(jī)制,詳細(xì)說,就是經(jīng)過頁表查找來對應(yīng)物理地址。準(zhǔn)確說分頁是CPU提供一個機(jī)制,Linux只是依據(jù)這種機(jī)制規(guī)則,利用它實現(xiàn)了內(nèi)存管理。在保護(hù)模式下,控制存放器CR0最高位PG位控制著分頁管理機(jī)制是否生效,假如PG=1,分頁機(jī)制生效,需經(jīng)過頁表查找才能把線性地址轉(zhuǎn)換物理地址。假如PG=0,則分頁機(jī)制無效,線性地址就直接做為物理地址。分頁基本原理是把內(nèi)存劃分成大小固定若干單元,每個單元稱為一頁(page),每頁包含4k字節(jié)地址空間(為簡化分析,我們不考慮擴(kuò)展分頁情況)。這么每一頁起始地址都是4k字節(jié)對齊。為了能轉(zhuǎn)換成物理地址,我們需要給CPU提供當(dāng)前任務(wù)線性地址轉(zhuǎn)物理地址查找表,即頁表(pagetable)。注意,為了實現(xiàn)每個任務(wù)平坦虛擬內(nèi)存,每個任務(wù)都有自己頁目錄表和頁表。為了節(jié)約頁表占用內(nèi)存空間,x86將線性地址經(jīng)過頁目錄表和頁表兩級查找轉(zhuǎn)換成物理地址。深入解析Linux內(nèi)存管理第8頁線性地址轉(zhuǎn)物理地址為了節(jié)約頁表占用內(nèi)存空間,x86將線性地址經(jīng)過頁目錄表和頁表兩級查找轉(zhuǎn)換成物理地址。32位線性地址被分成3個部分:最高10位Directory頁目錄表偏移量,中間10位Table是頁表偏移量,最低12位Offset是物理頁內(nèi)字節(jié)偏移量。頁目錄表大小為4k(剛好是一個頁大?。?,包含1024項,每個項4字節(jié)(32位),項目里存放內(nèi)容就是頁表物理地址。假如頁目錄表中頁表還未分配,則物理地址填0。頁表大小也是4k,一樣包含1024項,每個項4字節(jié),內(nèi)容為最終物理頁物理內(nèi)存起始地址。每個活動任務(wù),必須要先分配給它一個頁目錄表,并把頁目錄表物理地址存入cr3存放器。頁表能夠提前分配好,也能夠在用到時候再分配。還是以mov
0x80495b0,%eax中地址為例分析一下線性地址轉(zhuǎn)物理地址過程。前面說到Linux中邏輯地址等于線性地址,那么我們要轉(zhuǎn)換線性地址就是0x80495b0。轉(zhuǎn)換過程是由CPU自動完成,Linux所要做就是準(zhǔn)備好轉(zhuǎn)換所需頁目錄表和頁表(假設(shè)已經(jīng)準(zhǔn)備好,給頁目錄表和頁表分配物理內(nèi)存過程很復(fù)雜,后面再分析)。深入解析Linux內(nèi)存管理第9頁線性地址轉(zhuǎn)物理地址內(nèi)核先將當(dāng)前任務(wù)頁目錄表物理地址填入cr3存放器。線性地址0x80495b0轉(zhuǎn)換成二進(jìn)制后是00001000000001001001010110110000,最高10位0000100000十進(jìn)制是32,CPU查看頁目錄表第32項,里面存放是頁表物理地址。線性地址中間10位0001001001十進(jìn)制是73,頁表第73項存放是最終物理頁物理起始地址。物理頁基地址加上線性地址中最低12位偏移量,CPU就找到了線性地址最終對應(yīng)物理內(nèi)存單元。我們知道Linux中用戶進(jìn)程線性地址能尋址范圍是0-3G,那么是不是需要提前先把這3G虛擬內(nèi)存頁表都建立好呢?普通情況下,物理內(nèi)存是遠(yuǎn)遠(yuǎn)小于3G,加上同時有很多進(jìn)程都在運(yùn)行,根本無法給每個進(jìn)程提前建立3G線性地址頁表。Linux利用CPU一個機(jī)制處理了這個問題。進(jìn)程創(chuàng)建后我們能夠給頁目錄表表項值都填0,CPU在查找頁表時,假如表項內(nèi)容為0,則會引發(fā)一個缺頁異常,進(jìn)程暫停執(zhí)行,Linux內(nèi)核這時候能夠經(jīng)過一系列復(fù)雜算法給分配一個物理頁,并把物理頁地址填入表項中,進(jìn)程再恢復(fù)執(zhí)行。當(dāng)然進(jìn)程在這個過程中是被蒙蔽,它自己感覺還是正常訪問到了物理內(nèi)存。深入解析Linux內(nèi)存管理第10頁線性地址轉(zhuǎn)物理地址深入解析Linux內(nèi)存管理第11頁內(nèi)核頁表暫時內(nèi)核頁表最終內(nèi)核頁表深入解析Linux內(nèi)存管理第12頁暫時內(nèi)核頁表深入解析Linux內(nèi)存管理第13頁最終內(nèi)核頁表深入解析Linux內(nèi)存管理第14頁物理內(nèi)存1.內(nèi)核頁表2.內(nèi)存描述3.物理探測4.引導(dǎo)內(nèi)存5.Pre-CpuCache6.搭檔機(jī)制7.Slab機(jī)制深入解析Linux內(nèi)存管理第15頁1.內(nèi)核頁表structpage{ unsignedlongflags; atomic_t_count; union{ atomic_t_mapcount; unsignedintinuse; }; union{ struct{ unsignedlongprivate; structaddress_space*mapping; };#ifNR_CPUS>=CONFIG_SPLIT_PTLOCK_CPUS spinlock_tptl;#endif structkmem_cache*slab; /*SLUB:Pointertoslab*/ structpage*first_page; /*Compoundtailpages*/ }; union{ pgoff_tindex; /*Ouroffsetwithinmapping.*/ void*freelist; /*SLUB:freelistreq.slablock*/ }; structlist_headlru; #ifdefined(WANT_PAGE_VIRTUAL) void*virtual; #endif/*WANT_PAGE_VIRTUAL*/#ifdefCONFIG_CGROUP_MEM_RES_CTLR unsignedlongpage_cgroup;#endif};深入解析Linux內(nèi)存管理第16頁2.內(nèi)存描述-pglist_datatypedefstructpglist_data{ structzonenode_zones[MAX_NR_ZONES]; structzonelistnode_zonelists[MAX_ZONELISTS]; intnr_zones;#ifdefCONFIG_FLAT_NODE_MEM_MAP structpage*node_mem_map;#endif structbootmem_data*bdata;#ifdefCONFIG_MEMORY_HOTPLUG spinlock_tnode_size_lock;#endif unsignedlongnode_start_pfn; unsignedlongnode_present_pages;/*totalnumberofphysicalpages*/ unsignedlongnode_spanned_pages;/*totalsizeofphysicalpage range,includingholes*/ intnode_id; wait_queue_head_tkswapd_wait; structtask_struct*kswapd; intkswapd_max_order;}pg_data_t;深入解析Linux內(nèi)存管理第17頁2.內(nèi)存描述-zonestructzone{ /*Fieldscommonlyaccessedbythepageallocator*/ unsignedlong pages_min,pages_low,pages_high; unsignedlong lowmem_reserve[MAX_NR_ZONES];#ifdefCONFIG_NUMA intnode; unsignedlong min_unmapped_pages; unsignedlong min_slab_pages; structper_cpu_pageset *pageset[NR_CPUS];#else structper_cpu_pageset pageset[NR_CPUS];#endif spinlock_t lock;#ifdefCONFIG_MEMORY_HOTPLUG /*seespanned/present_pagesformoredescription*/ seqlock_t span_seqlock;#endif structfree_area free_area[MAX_ORDER];#ifndefCONFIG_SPARSEMEM unsignedlong *pageblock_flags;#endif/*CONFIG_SPARSEMEM*/ ZONE_PADDING(_pad1_) /*Fieldscommonlyaccessedbythepagereclaimscanner*/ spinlock_t lru_lock; structlist_head active_list; structlist_head inactive_list;深入解析Linux內(nèi)存管理第18頁2.內(nèi)存描述-zone unsignedlong nr_scan_inactive; unsignedlong pages_scanned; /*sincelastreclaim*/ unsignedlong flags; /*zoneflags,seebelow*/ /*Zonestatistics*/ atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS]; intprev_priority; ZONE_PADDING(_pad2_) /*Rarelyusedorread-mostlyfields*/ wait_queue_head_t *wait_table; unsignedlong wait_table_hash_nr_entries; unsignedlong wait_table_bits; structpglist_data *zone_pgdat; /*zone_start_pfn==zone_start_paddr>>PAGE_SHIFT*/ unsignedlong zone_start_pfn; unsignedlong spanned_pages; /*totalsize,includingholes*/ unsignedlong present_pages; /*amountofmemory(excludingholes)*/ /* *rarelyusedfields: */ constchar *name;}____cacheline_internodealigned_in_smp;深入解析Linux內(nèi)存管理第19頁深入解析Linux內(nèi)存管理第20頁物理探測在系統(tǒng)boot時候,kernel經(jīng)過0x15中止取得機(jī)器內(nèi)存容量。有三種參數(shù)88H(只能探測最大64MB內(nèi)存),E801H(得到大小),E820H(取得memorymap)。這個memorymap稱為E820圖,在kernel初始化代碼中會將這個memorymap復(fù)制到一個kernel中數(shù)據(jù)結(jié)構(gòu)e820map里,kernel需要經(jīng)過這個結(jié)構(gòu)來計算可用內(nèi)存容量。調(diào)用print_memory_map打印出各個內(nèi)存段范圍和類型,我內(nèi)存是2G,打印結(jié)果以下:[
0.000000]
BIOS-provided
physical
RAM
map:
[
0.000000]
BIOS-e820:
0000000000000000
-
000000000009f000
(usable)
[
0.000000]
BIOS-e820:
000000000009f000
-
00000000000a0000
(reserved)
[
0.000000]
BIOS-e820:
00000000000f0000
-
0000000000100000
(reserved)
[
0.000000]
BIOS-e820:
0000000000100000
-
0000000001e00000
(usable)
[
0.000000]
BIOS-e820:
0000000001e00000
-
0000000001e80040
(reserved)
[
0.000000]
BIOS-e820:
0000000001e80040
-
000000007bed0000
(usable)
[
0.000000]
BIOS-e820:
000000007bed0000
-
000000007bed3000
(ACPI
NVS)
[
0.000000]
BIOS-e820:
000000007bed3000
-
000000007bee0000
(ACPI
data)
[
0.000000]
BIOS-e820:
000000007bee0000
-
000000007bf00000
(reserved)
[
0.000000]
BIOS-e820:
000000007c000000
-
0000000080000000
(reserved)
[
0.000000]
BIOS-e820:
00000000f0000000
-
00000000f4000000
(reserved)
[
0.000000]
BIOS-e820:
00000000fec00000
-
0000000100000000
(reserved)
深入解析Linux內(nèi)存管理第21頁引導(dǎo)內(nèi)存深入解析Linux內(nèi)存管理第22頁P(yáng)re-CpuCache深入解析Linux內(nèi)存管理第23頁管理區(qū)分配器深入解析Linux內(nèi)存管理第24頁深入解析Linux內(nèi)存管理第25頁搭檔機(jī)制整體結(jié)構(gòu)深入解析Linux內(nèi)存管理第26頁搭檔機(jī)制Linux內(nèi)核經(jīng)過搭檔算法來管理物理內(nèi)存。搭檔系統(tǒng)(BuddySystem)在理論上是非常簡單內(nèi)存分配算法。它用途主要是盡可能降低外部碎片,同時允許快速分配與回收物理頁面。為了降低外部碎片,連續(xù)空閑頁面,依據(jù)空閑塊(由連續(xù)空閑頁面組成)大小,組織成不一樣鏈表(或者orders)。這么全部2個頁面大小空閑塊在一個鏈表中,4個頁面大小空閑塊在另外一個鏈表中,以這類推。深入解析Linux內(nèi)存管理第27頁搭檔機(jī)制注意,不一樣大小塊在空間上,不會有重合。當(dāng)一個需求為4個連續(xù)頁面時,檢驗是否有4個頁面空閑塊而快速滿足請求。若該鏈表上(每個結(jié)點都是大小為4頁面塊)有空閑塊,則分配給用戶,不然向下一個級別(order)鏈表中查找。若存在(8頁面)空閑塊(現(xiàn)處于另外一個級別鏈表上),則將該頁面塊分裂為兩個4頁面塊,一塊分配給請求者,另外一塊加入到4頁面塊鏈表中。這么能夠防止分裂大空閑塊,而此時有能夠滿足需求小頁面塊,從而降低外面碎片。深入解析Linux內(nèi)存管理第28頁Slab機(jī)制Linux所使用slab分配器基礎(chǔ)是JeffBonwick為SunOS操作系統(tǒng)首次引入一個算法。Jeff分配器是圍繞對象緩存進(jìn)行。在內(nèi)核中,會為有限對象集(比如文件描述符和其它常見結(jié)構(gòu))分配大量內(nèi)存。Jeff發(fā)覺對內(nèi)核中普通對象進(jìn)行初始化所需時間超出了對其進(jìn)行分配和釋放所需時間。所以他結(jié)論是不應(yīng)該將內(nèi)存釋放回一個全局內(nèi)存池,而是將內(nèi)存保持為針對特定目而初始化狀態(tài)。比如,假如內(nèi)存被分配給了一個互斥鎖,那么只需在為互斥鎖首次分配內(nèi)存時執(zhí)行一次互斥鎖初始化函數(shù)(mutex_init)即可。后續(xù)內(nèi)存分配不需要執(zhí)行這個初始化函數(shù),因為從上次釋放和調(diào)用析構(gòu)之后,它已經(jīng)處于所需狀態(tài)中了。Linuxslab分配器使用了這種思想和其它一些思想來構(gòu)建一個在空間和時間上都含有高效性內(nèi)存分配器。與傳統(tǒng)內(nèi)存管理模式相比,slab緩存分配器提供了很多優(yōu)點。首先,內(nèi)核通常依賴于對小對象分配,它們會在系統(tǒng)生命周期內(nèi)進(jìn)行無數(shù)次分配。slab緩存分配器經(jīng)過對類似大小對象進(jìn)行緩存而提供這種功效,從而防止了常見碎片問題。slab分配器還支持通用對象初始化,從而防止了為同一目而對一個對象重復(fù)進(jìn)行初始化。最終,slab分配器還能夠支持硬件緩存對齊和著色,這允許不一樣緩存中對象占用相同緩存行,從而提升緩存利用率并取得更加好性能。深入解析Linux內(nèi)存管理第29頁深入解析Linux內(nèi)存管理第30頁slab對象管理器深入解析Linux內(nèi)存管理第31頁深入解析Linux內(nèi)存管理第32頁slab對象管理器深入解析Linux內(nèi)存管理第33頁slab著色基本原理CPU訪問內(nèi)存時使用哪個cacheline是經(jīng)過低地址若干位確定,比如cacheline大小為32,那么是從bit5開始若干位。所以相距很遠(yuǎn)內(nèi)存地址,假如這些位地址相同,還是會被映射到同一個cacheline。Slabcache中存放是相同大小對象,假如沒有著色區(qū),那么同一個cache內(nèi),不一樣slab中含有相同slab內(nèi)部偏移對象,其低地址若干位是相同,映射到同一個cacheline。如圖所表示。深入解析Linux內(nèi)存管理第34頁slab著色基本原理如此一來,訪問cacheline沖突對象時,就會出現(xiàn)cachemiss,不停在cacheline和內(nèi)存之間往返切換,與此同時,其它cacheline可能無所事事,嚴(yán)重影響了cache效率。處理這一問題方法是經(jīng)過著色區(qū)使對象slab內(nèi)偏移各不相同,從而防止cacheline沖突。如圖所表示:深入解析Linux內(nèi)存管理第35頁slab著色基本原理著色貌似很好處理了問題,實質(zhì)不然,當(dāng)slab數(shù)目不多時,著色工作很好,當(dāng)slab數(shù)目很多時,著色發(fā)生了循環(huán),依然存在cacheline沖突問題。如圖所表示。第一與第四,第二與第五,第三與第六,這些slabcacheline是沖突。深入解析Linux內(nèi)存管理第36頁高端內(nèi)存非連續(xù)內(nèi)存固定映射內(nèi)存暫時內(nèi)存映射永久映射內(nèi)存深入解析Linux內(nèi)存管理第37頁地址映射深入解析Linux內(nèi)存管理第38頁虛擬內(nèi)存進(jìn)程虛擬地址空間數(shù)據(jù)結(jié)構(gòu)區(qū)域操作深入解析Linux內(nèi)存管理第39頁進(jìn)程虛擬地址空間<mm_types.h>structmm_struct{structvm_area_struct*mmap;/*listofVMAs*/structrb_rootmm_rb;structvm_area_struct*mmap_cache;/*lastfind_vmaresult*/...unsignedlong(*get_unmapped_area)(structfile*filp,unsignedlongaddr,unsignedlonglen,unsignedlongpgoff,unsignedlongflags);...unsignedlongmmap_base; /*baseofmmaparea*/unsignedlongtask_size; /*sizeoftaskvmspace*/...unsignedlongstart_code,end_code,start_data,end_data;unsignedlongstart_brk,brk,start_stack;unsignedlongarg_start,arg_end,env_start,env_end;...}深入解析Linux內(nèi)存管理第40頁地址映射深入解析Linux內(nèi)存管理第41頁虛擬內(nèi)存區(qū)域<mm_types.h>structvm_area_struct{ structmm_struct*vm_mm; /*Theaddressspacewebelongto.*/ unsignedlongvm_start; /*Ourstartaddresswithinvm_mm.*/ unsignedlongvm_end; /*Thefirstbyteafterourendaddress withinvm_mm.*/ /*linkedlistofVMareaspertask,sortedbyaddress*/ structvm_area_struct*vm_next; pgprot_tvm_page_prot; /*AccesspermissionsofthisVMA.*/ unsignedlongvm_flags; /*Flags,listedbelow.*/ structrb_nodevm_rb;/**Forareaswithanaddressspaceandbackingstore,*linkageintotheaddress_space->i_mmappriotree,or*linkagetothelistoflikevmashangingoffitsnode,or*linkageofvmaintheaddress_space->i_mmap_nonlinearlist.*/ union{ struct{ structlist_headlist;void*parent;/*alignswithprio_tree_nodeparent*/ structvm_area_struct*head; }vm_set;深入解析Linux內(nèi)存管理第42頁虛擬內(nèi)存區(qū)域 structraw_prio_tree_nodeprio_tree_node; }shared;/**Afile’sMAP_PRIVATEvmacanbeinbothi_mmaptreeandanon_vma*list,afteraCOWofoneofthefilepages.AMAP_SHAREDvma*canonlybeinthei_mmaptree.AnanonymousMAP_PRIVATE,stack*orbrkvma(withNULLfile)canonlybeinananon_vmalist.*/ structlist_headanon_vma_node; /*Serializedbyanon_vma->lock*/ structanon_vma*anon_vma; /*Serializedbypage_table_lock*/ /*Functionpointerstodealwiththisstruct.*/ structvm_operations_struct*vm_ops; /*Informationaboutourbackingstore:*/ unsignedlongvm_pgoff; /*Offset(withinvm_file)inPAGE_SIZE units,*not*PAGE_CACHE_SIZE*/ structfile*vm_file; /*Filewemapto(canbeNULL).*/ void*vm_private_data; /*wasvm_pte(sharedmem)*/};深入解析Linux內(nèi)存管理第43頁虛擬內(nèi)存區(qū)域深入解析Linux內(nèi)存管理第44頁虛擬內(nèi)存區(qū)域深入解析Linux內(nèi)存管理第45頁深入解析Linux內(nèi)存管理第46頁地址空間深入解析Linux內(nèi)存管理第47頁線性地址空間分布kernelcode/data/stackMemorymappedregionforsharedlibrariesruntimeheap(viamalloc)programtext(.text)initializeddata(.data)uninitializeddata(.bss)stackforbidden0%espprocessVMbrk0xc0physicalmemorysameforeachprocessprocess-specificdatastructures(pagetables,taskandmmstructs)kernelVM.data.textpdemand-zerodemand-zerolibc.so.data.text深入解析Linux內(nèi)存管理第48頁高速緩存Linux使用緩存頁高速緩沖深入解析Linux內(nèi)存管理第49頁Linux使用緩存不論在硬件設(shè)計還是軟件設(shè)計中,高速緩存是取得高性能慣用伎倆。Linux
使用了各種和內(nèi)存管理相關(guān)高速緩存。1.
緩沖區(qū)高速緩存:緩沖區(qū)高速緩存中包含了由塊設(shè)備使用數(shù)據(jù)緩沖區(qū)。這些緩沖區(qū)中包含了從設(shè)備中讀取數(shù)據(jù)塊或?qū)懭朐O(shè)備數(shù)據(jù)塊。緩沖區(qū)高速緩存由設(shè)備標(biāo)識號和塊標(biāo)號索引,所以能夠快速找出數(shù)據(jù)塊。假如數(shù)據(jù)能夠在緩沖區(qū)高速緩存中找到,則系統(tǒng)就沒有必要在物理塊設(shè)備上進(jìn)行實際讀操作。內(nèi)核為每個緩沖區(qū)維護(hù)很多信息以有利于緩解寫操作,這些信息包含一個“臟(dirty)”位,表示內(nèi)存中緩沖區(qū)已被修改,必須寫到磁盤;還包含一個時間標(biāo)志,表示緩沖區(qū)被刷新到磁盤之前已經(jīng)在內(nèi)存中停留了多長時間。因為緩沖區(qū)相關(guān)信息被保留在緩沖區(qū)首部,所以,這些數(shù)據(jù)結(jié)構(gòu)連同用戶數(shù)據(jù)本身緩沖區(qū)都需要維護(hù)。緩沖區(qū)高速緩存大小能夠改變。當(dāng)需要新緩沖區(qū)而現(xiàn)在又沒有可用緩沖區(qū)時,就按需分配頁面。當(dāng)空閑內(nèi)存變得不足時,比如上一節(jié)看到情況,就釋放緩沖區(qū)并重復(fù)使用對應(yīng)頁面。深入解析Linux內(nèi)存管理第50頁Linux使用緩存2.
頁面高速緩存頁面高速緩存是頁面I/O操作訪問數(shù)據(jù)所使用磁盤高速緩存。我們在文件系統(tǒng)會看到,read()、write()和mmap()系統(tǒng)調(diào)用對常規(guī)文件訪問都是經(jīng)過頁面高速緩存來完成。因為頁面I/O操作要傳輸整頁數(shù)據(jù),所以高速緩存中所保留信息單元是一個整頁面。一個頁面包含數(shù)據(jù)未必是物理上相鄰磁盤塊,所以就不能使用設(shè)備號和塊號來標(biāo)識頁面。相反,頁面高速緩存中一個頁面標(biāo)識是經(jīng)過文件索引節(jié)點和文件中偏移量到達(dá)。與頁面高速緩存相關(guān)操作主要有三種:當(dāng)訪問文件部分不在高速緩存中時增加一頁面,當(dāng)高速緩存變得太大時刪除一頁面,以及查找一個給定文件偏移量所在頁面。深入解析Linux內(nèi)存管理第51頁Linux使用緩存3.交換高速緩存只有修改后(臟)頁面才保留在交換文件中。修改后頁面寫入交換文件后,假如該頁面再次被交換但未被修改時,就沒有必要寫入交換文件,相反,只需丟棄該頁面。交換高速緩存實際包含了一個頁面表項鏈表,系統(tǒng)每個物理頁面對應(yīng)一個頁面表項。對交換出頁面,該頁面表項包含保留該頁面交換文件信息,以及該頁面在交換文件中位置信息。假如某個交換頁面表項非零,則表明保留在交換文件中對應(yīng)物理頁面沒有被修改。假如這一頁面在后續(xù)操作中被修改,則處于交換緩存中頁面表項被清零。
Linux
需要從物理內(nèi)存中交換出某個頁面時,它首先分析交換緩存中信息,假如緩存中包含該物理頁面一個非零頁面表項,則說明該頁面交換出內(nèi)存后還沒有被修改過,這時,系統(tǒng)只需丟棄該頁面。4.硬件高速緩存常見硬件緩存是對頁面表項緩存,這一工作實際由處理器完成,其操作和詳細(xì)處理器硬件相關(guān)(但管理要由軟件完成)。深入解析Linux內(nèi)存管理第52頁頁高速緩沖頁高速緩存緩存是頁面。緩存中頁來自對正規(guī)文件、塊設(shè)備文件和內(nèi)存映射文件讀寫,如此一來,頁高速緩存內(nèi)就包含了最近被訪問過文件全部頁面。在執(zhí)行I/O操作前,比如read()操作,內(nèi)核會檢驗數(shù)據(jù)是否已經(jīng)在頁高速緩存中了,假如所需數(shù)據(jù)確實在高速緩存中,那么內(nèi)核就能夠馬上從緩存中得到所需頁,而不需要從磁盤讀取數(shù)據(jù)。深入解析Linux內(nèi)存管理第53頁頁框回收PFRA設(shè)計反向映射匿名頁反向映射優(yōu)先搜索樹PFRA實現(xiàn)LRU鏈表內(nèi)存緊缺回收深入解析Linux內(nèi)存管理第54頁P(yáng)FRA設(shè)計頁類型說明處理方式不可回收頁空閑頁(包含在搭檔系統(tǒng)列表中)保留頁(PG_reserved標(biāo)志置位)內(nèi)核動態(tài)分配頁(slab或alloc_pages分配)進(jìn)程內(nèi)核態(tài)堆棧頁暫時時鎖定頁(PG_locked標(biāo)志置位)內(nèi)存鎖定頁(在線性區(qū)中且VM_LOCKED標(biāo)志置位)不允許也無需回收可交換頁用戶態(tài)地址空間匿名頁tmpfs文件系統(tǒng)暫時頁(如IPC共享內(nèi)存頁)將頁內(nèi)容保存在交換區(qū)中可同時頁用戶態(tài)地址空間映射頁存有磁盤文件數(shù)據(jù)頁高速緩存頁塊設(shè)備緩存頁一些磁盤高速緩存頁(如磁盤索引節(jié)點高速緩存)必要時,與磁盤映像同時這些頁可丟棄頁內(nèi)存高速緩存中未使用頁(如slab分配器高速緩存)目錄項高速緩存未使用頁無需處理頁框回收算法(pageframereclaimingalgorithm,PFRA)目標(biāo)就是取得頁框并使之空閑。深入解析Linux內(nèi)存管理第55頁反向映射struct
page{
unsignedlongflags;
atomic_t_count; /*Usagecount,seebelow.*/ union{
atomic_t
_mapcount;
unsignedint
inuse; /*SLUB:Nrofobjects*/ };union{
struct{ unsignedlongprivate;
struct
address_space*mapping;
};
struct
kmem_cache*slab; /*SLUB:Pointertoslab*/
structpage*first_page; /*Compoundtailpages*/};
union{
pgoff_t
index;
void*freelist; };…};深入解析Linux內(nèi)存管理第56頁反向映射因為PFRA目標(biāo)之一是能釋放共享頁框。為到達(dá)這個目標(biāo),Linux2.6內(nèi)核能夠快速定位指向同一頁框全部頁表項。這個過程就叫做反向映射(reversemapping)。反向映射方法簡單處理之道,就是在頁描述符中引人附加字段,從而將某頁描述符所確定頁框中對應(yīng)全部頁表項聯(lián)接起來。不過,保持更新這么鏈表將會大大增加系統(tǒng)開銷,所以,就有更成熟方法設(shè)計出來了。Linux2.6就有叫做“面向?qū)ο蠓聪蛴成洹奔夹g(shù)。_mapcount字段存放引用頁框頁表項數(shù)目。計數(shù)器起始值為-1,這表示沒有頁表項(不包含內(nèi)核頁表)引用該頁框;假如值為0,就表示頁是非共享;而假如值大于0(比如是n),則表示頁是共享,而且有n+1個頁表共享它。page_mapcount
函數(shù)接收頁描述符地址,返回值為_mapcount+l(這么,如返回值為1,表明是某個進(jìn)程用戶態(tài)地址空間中存放一個非共享頁)。頁描述符mapping字段用于確定頁是映射或匿名。說明以下:1).假如mapping字段空,則該頁屬于交換高速緩存。2).假如mapping字段非空,且最低位是1,表示該頁為匿名頁;同時mapping字段中存放是指向anon_vma描述符指針。3).假如mapping字段非空,且最低位是0,表示該頁為映射頁;同時mapping字段指向?qū)?yīng)文件address_space對象。深入解析Linux內(nèi)存管理第57頁匿名頁反向映射struct
anon_vma{
spinlock_tlock; /*Serializeaccesstovmalist*/
struct
list_headhead; /*Listofprivate"related"vmas*/};匿名頁經(jīng)常是由幾個進(jìn)程共享。最為常見情形是:創(chuàng)建新進(jìn)程——父進(jìn)程全部頁面,包含匿名頁,同時也以只讀形式讓子進(jìn)程頁表項指向。另外(但不常見),進(jìn)程創(chuàng)建線性區(qū)時使用兩個標(biāo)志MAP_ANONYMOUS
和MAP_SHARED,表明這個線性區(qū)域內(nèi)頁將由該進(jìn)程后面子進(jìn)程共享。Linux使用一個非常簡單策略:將引用同一個頁框全部匿名線性區(qū)鏈接起來,也就是說將該頁框所在匿名線性區(qū)存放在一個雙向循環(huán)鏈表中。注意!一個匿名線性區(qū)有可能很大,會存有多個頁,但因為這些頁面是連續(xù),所以有且一直只有一個反向映射鏈表用于該區(qū)域中全部頁面。當(dāng)為一個匿名線性區(qū)分配第一頁時,內(nèi)核創(chuàng)建一個新anon_vma數(shù)據(jù)結(jié)構(gòu)深入解析Linux內(nèi)存管理第58頁匿名頁反向映射lock
字段是競爭條件下保護(hù)鏈表自旋鎖;head字段是線性區(qū)描述符雙向循環(huán)鏈表頭部。然后,內(nèi)核將匿名線性區(qū)vm_area_struct描述符插入anon_vma鏈表。為實現(xiàn)這個目標(biāo),vm_area_struct數(shù)據(jù)結(jié)構(gòu)中包含有對應(yīng)該鏈表兩個字段:anon_vma_node和anon_vma。anon_vma_node字段存放指向鏈表中前一個和后一個元素指針,而anon_vma字段指向anon_vma數(shù)據(jù)結(jié)構(gòu)。最終,按前面所述,內(nèi)核將anon_vma數(shù)據(jù)結(jié)構(gòu)地址存放在匿名頁描述符mapping字段。如圖所表示深入解析Linux內(nèi)存管理第59頁匿名頁反向映射深入解析Linux內(nèi)存管理第60頁匿名頁反向映射lock
字段是競爭條件下保護(hù)鏈表自旋鎖;head字段是線性區(qū)描述符雙向循環(huán)鏈表頭部。然后,內(nèi)核將匿名線性區(qū)vm_area_struct描述符插入anon_vma鏈表。為實現(xiàn)這個目標(biāo),vm_area_struct數(shù)據(jù)結(jié)構(gòu)中包含有對應(yīng)該鏈表兩個字段:anon_vma_node和anon_vma。anon_vma_node字段存放指向鏈表中前一個和后一個元素指針,而anon_vma字段指向anon_vma數(shù)據(jù)結(jié)構(gòu)。最終,按前面所述,內(nèi)核將anon_vma數(shù)據(jù)結(jié)構(gòu)地址存放在匿名頁描述符mapping字段。如圖所表示深入解析Linux內(nèi)存管理第61頁匿名頁反向映射當(dāng)已被一個進(jìn)程引用頁面插入另一個進(jìn)程頁表項時(比如調(diào)用fork()系統(tǒng)調(diào)用時),內(nèi)核只是將第二個進(jìn)程匿名線性區(qū)插入anon_vma數(shù)據(jù)結(jié)構(gòu)雙向循環(huán)鏈表,而第一個進(jìn)程線性區(qū)anon_vma字段指向該anon_vma數(shù)據(jù)結(jié)構(gòu)。所以每個anon_vma鏈表通常包含不一樣進(jìn)程線性區(qū)。綜上,借助anon_vma鏈表,內(nèi)核能夠快速定位引用同一匿名頁框全部頁表項。實際上,每個區(qū)域描述符在vm_mm字段中存放內(nèi)存描述符地址,而該內(nèi)存描述符又有一個pgd字段,其中存有進(jìn)程頁全局目錄。這么,頁表項就能夠從匿名頁起始線性地址得到,而該匿名頁線性地址能夠由線性區(qū)描述符vm_start字段以及頁描述符index字段得到。深入解析Linux內(nèi)存管理第62頁try_to_unmap_one深入解析Linux內(nèi)存管理第63頁優(yōu)先搜索樹映射頁面向?qū)ο蠓聪蛴成渌谒枷胍唵蔚枚嗔耍何覀兛偸悄軌蛉〉弥赶蛞粋€給定頁框頁表項,方法就是訪問對應(yīng)映射頁所在線性區(qū)描述符。所以,反向映射關(guān)鍵就是一個巧妙數(shù)據(jù)結(jié)構(gòu),這個數(shù)據(jù)結(jié)構(gòu)能夠存放與給定頁框相關(guān)全部線性區(qū)描述符。匿名線性區(qū)描述符存放在雙向循環(huán)鏈表中。取得引用給定頁框全部頁表項,就是對該鏈表中元素進(jìn)行線性掃描。共享匿名頁框數(shù)量不是很大,所以這個方法工作得很好。與匿名頁相反,映射頁經(jīng)常是共享,這是因為不一樣進(jìn)程常會共享同一個程序代碼。比如,幾乎全部進(jìn)程都會共享包含標(biāo)準(zhǔn)C庫代碼頁面。所以,Linux2.6依靠叫做“優(yōu)先搜索樹(prioritysearchtree)”結(jié)構(gòu)來快速定位引用同一頁框全部線性區(qū)。每個文件對應(yīng)一個優(yōu)先搜索樹。它存放在address_space
對象i_mmap字段中,該address_space對象包含在文件索引節(jié)點對象中。因為映射頁描述符mapping
字段指向address_space對象,所以總是能夠快速檢索搜索樹根:深入解析Linux內(nèi)存管理第64頁優(yōu)先搜索樹PST樹是一個堆和對稱搜索樹混合體,PST中每一個區(qū)間相當(dāng)于一個樹節(jié)點,它由基索引(radixindex)和堆索引(heapindex)兩個索引來標(biāo)識?;饕硎緟^(qū)間起始點而堆索引表示終點。每個線性區(qū)能夠被看成是文件頁在物理內(nèi)存中一個區(qū)間,并由在文件中起始位置(基索引)和終點位置(堆索引)所確定。struct
address_space
{
struct
inode
*host; /*owner:inode,block_device*/
struct
radix_tree_root
page_tree; /*radixtreeofallpages*/
rwlock_t
tree_lock; /*andrwlockprotectingit*/ unsignedint
i_mmap_writable; /*countVM_SHAREDmappings*/
struct
prio_tree_root
i_mmap;
/*treeofprivateandsharedmappings*/}__attribute__((aligned(sizeof(long))));深入解析Linux內(nèi)存管理第65頁優(yōu)先搜索樹<fs.h>structfile{...structaddress_space*f_mapping;...}<fs.h>structinode{...structaddress_space*i_mapping;...}深入解析Linux內(nèi)存管理第66頁優(yōu)先搜索樹深入解析Linux內(nèi)存管理第67頁優(yōu)先搜索樹子節(jié)點堆索引都小于對應(yīng)父節(jié)點堆索引。任意一個節(jié)點左子節(jié)點基索引也都小于右子節(jié)點基索引,假如基索引相等,則按照大小索引排序。深入解析Linux內(nèi)存管理第68頁P(yáng)FRA實現(xiàn)頁框回收算法必須處理各種屬于用戶態(tài)進(jìn)程、磁盤高速緩存和內(nèi)存高速緩存頁,而且必須遵照幾條試探法準(zhǔn)則。所以,PFRA有很多函數(shù)也就不奇怪了。在ULK-3中一個圖列出了PFRA主要函數(shù),箭頭表示函數(shù)調(diào)用。比如,try_to_free_pages()函數(shù)調(diào)shrink_zones()、shrink_slab()和out_of_memory()三個函數(shù):我們看到PFRA有三個入口,對應(yīng)著頁框回收算法執(zhí)行有三種基本情形:內(nèi)存緊缺回收:內(nèi)核發(fā)覺內(nèi)存緊缺睡眠回收:在進(jìn)人suspend-to-disk狀態(tài)時,內(nèi)核必須釋放內(nèi)存(我們不研究這種情形)周期回收:必要時,周期性激活內(nèi)核線程執(zhí)行內(nèi)存回收算法深入解析Linux內(nèi)存管理第69頁深入解析Linux內(nèi)存管理第70頁LRU鏈表LRU鏈表是頁面回收算法關(guān)鍵數(shù)據(jù)結(jié)構(gòu),屬于進(jìn)程用戶態(tài)地址空間或頁高速緩存全部頁被分成兩組:活動鏈表與非活動鏈表。它們被統(tǒng)稱為LRU鏈表。前面一個鏈表用于存放最近被訪問過頁;后面則存放有一段時間沒有被訪問過頁。顯然,頁必須從非活動鏈表中“竊取”。這兩個雙向鏈表頭分別存放在每個zone描述符active_1ist和inactive_list字段,而該描述符nr_active和nr_inactive字段表示存放在兩個鏈表中頁數(shù)。最終,lru_lock字段是一個自旋鎖,保護(hù)兩個鏈表免受SMP系統(tǒng)上并發(fā)訪問:struct
zone{ …… /*Fieldscommonlyaccessedbythepagereclaimscanner*/
spinlock_t
lru_lock;
struct
list_head
active_list;
struct
list_head
inactive_list;
unsignedlong nr_scan_active; unsignedlong nr_scan_inactive; unsignedlong pages_scanned; /*sincelastreclaim*/ unsignedlong flags; /*zoneflags,seebelow*/
……}深入解析Linux內(nèi)存管理第71頁LRU鏈表假如頁屬于LRU鏈表,則設(shè)置頁描述符中page數(shù)據(jù)結(jié)構(gòu)PG_lru標(biāo)志。另外,假如頁屬于活動鏈表,則設(shè)置將page數(shù)據(jù)結(jié)構(gòu)flagsPG_active置位,而假如頁屬于非活動鏈表,則清PG_active標(biāo)志。頁描述符lru字段存放指向LRU鏈表中下一個元素和前一個元素指針。另外有幾個輔助函數(shù)處理LRU鏈表:add_page_to_active_list()將頁加入管理區(qū)活動鏈表頭部并遞增管理區(qū)描述符nr_active字段。del_page_from_active_list()從管理區(qū)活動鏈表中刪除頁并遞減管理區(qū)描述符nr_active字段。lru_cache_add_active()假如頁不在LRU鏈表中,將PGlru和PGactive標(biāo)志置位,得到管理區(qū)lru_lock自旋鎖,調(diào)用add_page_to_active_list()把頁插入管理區(qū)活動鏈表。實際上,最終兩個函數(shù),lru_cache_add()和lru_cache_add_active()稍有些復(fù)雜。這兩個函數(shù)實際上并沒有立刻把頁移到LRU,而是在pagevec類型暫時數(shù)據(jù)結(jié)構(gòu)中聚集這些頁,每個結(jié)構(gòu)能夠存放多達(dá)14個頁描述符指針。只有當(dāng)一個pagevec結(jié)構(gòu)寫滿了,頁才真正被移到LRU鏈表中。這種機(jī)制能夠改進(jìn)系統(tǒng)性能,這是因為只當(dāng)LRU鏈表實際修改后才取得LRU自旋鎖。深入解析Linux內(nèi)存管理第72頁shrink_page_list深入解析Linux內(nèi)存管理第73頁交換機(jī)制交換機(jī)制概述交換區(qū)數(shù)據(jù)結(jié)構(gòu)激活和禁用交換區(qū)分配和釋放頁槽頁面換入和換出深入解析Linux內(nèi)存管理第74頁交換機(jī)制概述交換,用來為非映射頁在磁盤上提供備份。從前面討論我們知道有三類頁必須由交換子系統(tǒng)處理:1)屬于進(jìn)程匿名線性區(qū)(比如,用戶態(tài)堆棧和堆)頁。2)屬于進(jìn)程私有內(nèi)存映射臟頁。3)屬于IPC共享內(nèi)存區(qū)頁。就像請求調(diào)頁,交換對于程序必須是透明?;叵胍幌?,我們知道每個頁表項包含一個Present標(biāo)志。內(nèi)核利用這個標(biāo)志來通知屬于某個進(jìn)程地址空間頁已被換出。在這個標(biāo)志之外,Linux還利用頁表項中其它位存放換出頁標(biāo)識符(swapped-outpageidentifier)。該標(biāo)識符用于編碼換出頁在磁盤上位置。當(dāng)缺頁異常發(fā)生時,對應(yīng)異常處理程序能夠檢測到該頁不在RAM中,然后調(diào)用函數(shù)從磁盤換入該缺頁。交換子系統(tǒng)主要功效總結(jié)以下:1)在磁盤上建立交換區(qū)(swaparea),用于存放沒有磁盤映像頁。2)管理交換區(qū)空間。當(dāng)需求發(fā)生時,分配與釋放頁槽(pageslot)。3)提供函數(shù)用于從RAM中把頁換出(swapout)到交換區(qū)或從交換區(qū)換入(swapin)到RAM中。4)利用頁表項(現(xiàn)已被換出換出頁頁表項)中換出頁標(biāo)識符跟蹤數(shù)據(jù)在交換區(qū)中位置。深入解析Linux內(nèi)存管理第75頁交換區(qū)數(shù)據(jù)結(jié)構(gòu)從內(nèi)存中換出頁存放在交換區(qū)(swaparea)中,交換區(qū)實現(xiàn)能夠使用自己磁盤分區(qū),也能夠使用包含在大型分區(qū)中文件。能夠定義幾個不一樣交換區(qū),最大個數(shù)由MAX_SWAPFILES宏(通常被設(shè)置成32)確定。每個交換區(qū)都由一組頁槽(pageslot)組成,也就是說,由一組4096字節(jié)大小塊組成,每塊中包含一個換出頁。交換區(qū)第一個頁槽用來永久存放相關(guān)交換區(qū)信息,其格式由swap_header聯(lián)合體(由兩個結(jié)構(gòu)info和magic組成)來描述。magic結(jié)構(gòu)提供了一個字符串,用來把磁盤某部分明確地標(biāo)識成交換區(qū),它只含有一個字段magic.magic,這個字段含有一個10字符“magic”字符串。magic結(jié)構(gòu)從根本上允許內(nèi)核明確地把一個文件或分區(qū)標(biāo)識成交換區(qū),這個字符串內(nèi)容就是“SWAPSPACE2”。該字段通常位于第一個頁槽末尾。深入解析Linux內(nèi)存管理第76頁swap_headerunionswap_header{
struct{ charreserved[PAGE_SIZE-10]; charmagic[10]; /*SWAP-SPACEorSWAPSPACE2*/ }magic;
struct{ char bootbits[1024]; /*Spacefordisklabeletc.*/
__u32 version; __u32 last_page; __u32 nr_badpages; unsignedchar sws_uuid[16]; unsignedchar sws_volume[16]; __u32 padding[117]; __u32 badpages[1]; }info;};深入解析Linux內(nèi)存管理第77頁交換區(qū)數(shù)據(jù)結(jié)構(gòu)info 結(jié)構(gòu)字段以下:bootbits:交換算法不使用該字段。該字段對應(yīng)于交換區(qū)第一個1024字節(jié),能夠存放分區(qū)數(shù)據(jù)、磁盤標(biāo)簽等等。version:交換算法版本。last_page:可有效使用最終一個頁槽。nr_badpages:有缺點頁槽個數(shù)。padding[117]:填充字節(jié)。badpages[1]:一共637個數(shù)字,用來指定有缺點頁槽位置。深入解析Linux內(nèi)存管理第78頁交換區(qū)描述符struct
swap_info_struct{ unsignedintflags;
int
prio;
/*swappriority*/
structfile*swap_file;
/*指針,指向存放交換區(qū)普通文件或設(shè)備文件文件對象*/
struct
block_device*bdev;
struct
list_head
extent_list;
/*組成交換區(qū)子區(qū)鏈表頭部*/
struct
swap_extent*curr_swap_extent;
/*指向最近使用子區(qū)描述符指針*/ unsignedold_block_size; unsignedshort*swap_map; /*指向計數(shù)器數(shù)組指針,
交換區(qū)每個頁槽對應(yīng)一個數(shù)組元素*/ unsignedint
lowest_bit; unsignedint
highest_bit; unsignedint
cluster_next; unsignedint
cluster_nr; unsignedintpages; unsignedintmax; unsignedint
inuse_pages;
intnext;
/*nextentryonswaplist*/};深入解析Linux內(nèi)存管理第79頁深入解析Linux內(nèi)存管理第80頁創(chuàng)建交換區(qū)系統(tǒng)管理員在創(chuàng)建Linux系統(tǒng)中其它分區(qū)時都創(chuàng)建一個交換分區(qū),然后使用mkswap命令把這個磁盤區(qū)設(shè)置成一個新交換區(qū)。該命令對剛才介紹第一個頁槽中字段進(jìn)行初始化。因為磁盤中可能會有一些壞塊,這個程序還能夠?qū)ζ渌宽摬圻M(jìn)行檢驗從而確定有缺點頁槽位置。不過執(zhí)行mkswap命令會把交換區(qū)設(shè)置成非激活狀態(tài)。每個交換區(qū)都能夠在系統(tǒng)開啟時在腳本文件中被激活,也能夠在系統(tǒng)運(yùn)行之后動態(tài)激活。每個交換區(qū)由一個或多個交換子區(qū)(swapextent)組成,每個交換子區(qū)由一個swap_extent描述符表示,每個子區(qū)對應(yīng)一組頁(更準(zhǔn)確地說,是一組頁槽),它們在磁盤上是物理相鄰。swap_extent描述符由下面這幾部分組成:交換區(qū)子區(qū)首頁索引、子區(qū)頁數(shù)和子區(qū)起始磁盤扇區(qū)號。當(dāng)激活交換區(qū)本身同時,組成交換區(qū)有序子區(qū)鏈表也被創(chuàng)建。存放在磁盤分區(qū)中交換區(qū)只有一個子區(qū);不過,存放在普通文件中交換區(qū)則可能有多個子區(qū),這是因為文件系統(tǒng)有可能沒把該文件全部分配在磁盤一組連續(xù)塊中。setup_swap_extents->add_swap_extent(sis,0,sis->max,0);深入解析Linux內(nèi)存管理第81頁創(chuàng)建交換區(qū)swap_info數(shù)組包含MAX_SWAPFILES個交換區(qū)描述符。只有那些設(shè)置了SWP_USED標(biāo)志交換區(qū)才被使用,因為它們是活動區(qū)域。下列圖說明了swap_info數(shù)組(其數(shù)組元素為swap_info_struct)、一個交換區(qū)和對應(yīng)計數(shù)器數(shù)組情況:系統(tǒng)中有一個全局變量nr_swapfiles,它存放數(shù)組中包含或已包含所使用交換區(qū)描述符最終一個元素索引。這個變量有些名不符實,它并沒有包含活動交換區(qū)個數(shù)?;顒咏粨Q區(qū)描述符也被插入按交換區(qū)優(yōu)先級排序鏈表中。該鏈表是經(jīng)過交換區(qū)描述符next字段實現(xiàn),next字段存放是swap_info數(shù)組中下一個描述符索引。該字段作為索引這種使用方法與我們已經(jīng)見過很多名為next字段使用方法有所不一樣,后者通常都是指針。swap_list_t類型swap_list全局變量包含以下字段:structswap_list_tswap_list={-1,-1};structswap_list_t{inthe
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025廣告制作合同協(xié)議范本
- 2025水果代銷合同范本
- 2025建筑工程施工監(jiān)理合同
- 2025年合同履行情況自我評估:合同執(zhí)行工作個人鑒定撰寫
- 英語聽力掌控秘籍
- 2025合同范本:技術(shù)服務(wù)合同模板
- 2025勞動爭議調(diào)解協(xié)議合同樣本
- 銀行業(yè)掌握與提升
- 藝術(shù)大師解析
- 2025《國際服務(wù)銷售合同公約》若干問題研究
- 2025年高考?xì)v史總復(fù)習(xí)高中歷史必修二八大專題知識復(fù)習(xí)提綱
- 2025事業(yè)單位考試題庫及答案200題
- 臨床執(zhí)業(yè)醫(yī)師考試健康教育技能試題及答案
- 機(jī)車車輛試題及答案
- 地理澳大利亞課件-2024-2025學(xué)年人教版(2024)初中地理七年級下冊
- 常用施工規(guī)定和技術(shù)要求1
- 新版《醫(yī)療器械經(jīng)營質(zhì)量管理規(guī)范》(2024)培訓(xùn)試題及答案
- 健合集團(tuán)筆試在線測評題
- 禮儀文書寫作課件
- 20CrMnTi較詳細(xì)材料屬性
- 99S203 消防水泵接合器安裝圖集
評論
0/150
提交評論