一、系統調用mmap
虛擬內存區域使用起始地址和結束地址描述,鏈表按起始地址遞增排序。兩系統調用區別:mmap指定的偏移的單位是字節,而mmap2指定的偏移的單位是頁。ARM64架構實現系統調用mmap。

二、系統調用munmap
系統調用munmap用來刪除內存映射,它有兩個參數:起始地址和長度即可。它的主要工作委托給內核源碼文件處理“mm/mmap.c”中的函數do_munmap。
vm_munmap -->do_munmap -->vma=find_vma(mm,start) -->error=__split_vma(mm,vma,start,0) -->last=find_vma(mm,end) -->interror=__split_vma(mm,last,end,1) -->munlock_vma_pages_all -->detach_vmas_to_be_unmapped -->unmap_region -->arch_unmap -->remove_vma_list
vma = find_vma(mm,start);//根據起始地址找到要刪除的第一個虛擬內存區域vma
error = __split_vma(mm,vma,start,0);//如果只刪除虛擬內存區域vma的部分,那么分裂虛擬內存區域vma
last = find_vma(mm,end);//根據結束地址找到要刪除的最后一個虛擬內存區域vma
int error = __split_vma(mm,last,end,1);//如果只刪除虛擬內存區域last的一部分,那么分裂虛擬內存區域vma
munlock_vma_pages_all;//針對所有刪除目標,如果虛擬內存區域被鎖定在內存中(不允許換出到交換區),調用函數解除鎖定
detach_vmas_to_be_unmapped;//調用此函數,把所有刪除目標從進程虛擬內存區域鏈表和樹中刪除,單獨組成一條臨時鏈表
unmap_region;//調用此函數,針對所有刪除目標,在進程的頁表中刪除映射,并且從處理器的頁表緩存中刪除映射
arch_unmap;//調用此函數執行處理器架構特定的處理操作
remove_vma_list;//調用此函數,刪除所有目標
三、物理內存組織結構
1.體系結構
目前多處理器系統有兩種體系結構:
非一致內存訪問(Non-Unit Memory Access,NUMA):指內存被劃分成多個內存節點的多處理器系統。訪問一個內存節點花費的時間取決于處理器和內存節點的距離。
對稱多處理器(Sysmmetric Muti-Processor,SMP):即一致內存訪問(Uniform Memory Access,UMA),所有處理器訪問內存花費的時間是相同的。

2.內存模型
內存模型是從處理器角度看到的物理內存分布,內核管理不同內存模型的方式存在差異。內存管理子系統支持3種內存模型:
平坦內存(Flat Memory):內存的物理地址空間是連續的,沒有空洞。
不連續內存(Discontiguous Memory):內存的物理地址空間存在空洞,這種模型可以高效地處理空洞。
稀疏內存(Space Memory):內存物理地址空間存在空洞,如果要支持內存熱插拔,只能選擇稀疏內存模型。
3.三級結構
內存管理子系統使用節點(node)、區域(zone)、頁(page)三級結構描述物理內存。
3.1 內存節點--->分為兩種情況
NUMA體系的內存節點,根據處理器和內存距離劃分;
在具有不連續內存的NUMA系統中,表示比區域的級別更高的內存區域,根據物理地址是否連續,每塊物理地址連續的內存是一個內存節點。
內存節點使用結構體pglist_data描述內存布局
Linux內核源碼如下:
typedefstructpglist_data{
structzonenode_zones[MAX_NR_ZONES];//內存區域數組
structzonelistnode_zonelists[MAX_ZONELISTS];//備用區域列表
intnr_zones;//該節點包含內存區域數量
#ifdefCONFIG_FLAT_NODE_MEM_MAP/*means!SPARSEMEM*///除了稀疏內存模型以外
structpage*node_mem_map;//頁描述符數組
#ifdefCONFIG_PAGE_EXTENSION
structpage_ext*node_page_ext;//頁的擴展屬性
#endif
#endif
#ifndefCONFIG_NO_BOOTMEM
structbootmem_data*bdata;
#endif
#ifdefCONFIG_MEMORY_HOTPLUG
/*
*Mustbeheldanytimeyouexpectnode_start_pfn,node_present_pages
*ornode_spanned_pagesstayconstant.Holdingthiswillalso
*guaranteethatanypfn_valid()staysthatway.
*
*pgdat_resize_lock()andpgdat_resize_unlock()areprovidedto
*manipulatenode_size_lockwithoutcheckingforCONFIG_MEMORY_HOTPLUG.
*
*Nestsabovezone->lockandzone->span_seqlock
*/
spinlock_tnode_size_lock;
#endif
unsignedlongnode_start_pfn;//該節點的起始物理頁號
unsignedlongnode_present_pages;/*物理頁總數*/
unsignedlongnode_spanned_pages;/*物理頁范圍總的長度,包括空間*/
intnode_id;//節點標識符
wait_queue_head_tkswapd_wait;
wait_queue_head_tpfmemalloc_wait;
structtask_struct*kswapd;/*Protectedby
mem_hotplug_begin/end()*/
intkswapd_max_order;
enumzone_typeclasszone_idx;
#ifdefCONFIG_NUMA_BALANCING
/*Lockserializingthemigrateratelimitingwindow*/
spinlock_tnumabalancing_migrate_lock;
/*Ratelimitingtimeinterval*/
unsignedlongnumabalancing_migrate_next_window;
/*Numberofpagesmigratedduringtheratelimitingtimeinterval*/
unsignedlongnumabalancing_migrate_nr_pages;
#endif
#ifdefCONFIG_DEFERRED_STRUCT_PAGE_INIT
/*
*Ifmemoryinitialisationonlargemachinesisdeferredthenthis
*isthefirstPFNthatneedstobeinitialised.
*/
unsignedlongfirst_deferred_pfn;
#endif/*CONFIG_DEFERRED_STRUCT_PAGE_INIT*/
}pg_data_t;
node_mem_map此成員指向頁描述符數組,每個物理頁對應一個頁描述符。
Node是內存管理最頂層的結構,在NUMA架構下,CPU平均劃分為多個Node,每個Node有自己的內存控制器及內存插槽。CPU訪問自己Node上內存速度快,而訪問其他CPU所關聯Node的內存速度慢。UMA被當作只一個Node的NUMA系統。
3.2 內存區域(zone)
內存節點被劃分為內存區域。Linux內核源碼分析:include/linux/mmzone.h
enumzone_type{
#ifdefCONFIG_ZONE_DMA
/*
*ZONE_DMAisusedwhentherearedevicesthatarenotable
*todoDMAtoallofaddressablememory(ZONE_NORMAL).Thenwe
*carveouttheportionofmemorythatisneededforthesedevices.
*Therangeisarchspecific.
*
*Someexamples
*
*ArchitectureLimit
*---------------------------
*parisc,ia64,sparc<4G
??*?s390???<2G
??*?arm???Various
??*?alpha??Unlimited?or?0-16MB.
??*
??*?i386,?x86_64?and?multiple?other?arches
??*????<16M.
??*/
?ZONE_DMA,?/*Direct Memory Access,直接內存訪問。如果有些設備不能直接訪問所有內存,需要使用DMA區域。ISA*/
#endif
#ifdef?CONFIG_ZONE_DMA32
?/*
??*?x86_64?needs?two?ZONE_DMAs?because?it?supports?devices?that?are
??*?only?able?to?do?DMA?to?the?lower?16M?but?also?32?bit?devices?that
??*?can?only?do?DMA?areas?below?4G.
??*/
?ZONE_DMA32,?/*?64位系統,如果既要支持能直接訪問16MB以下內存設備,又要支持能直接訪問4GB以下內存的32設備,必須使用此DMA32區域*/
#endif
?/*
??*?Normal?addressable?memory?is?in?ZONE_NORMAL.?DMA?operations?can?be
??*?performed?on?pages?in?ZONE_NORMAL?if?the?DMA?devices?support
??*?transfers?to?all?addressable?memory.
??*/
?/*普通內存區域:
?直接映射到內核虛擬地址空間的內存區域,又稱為普通區域,又稱為直接映射區域,又稱為線性映射區域*/
?ZONE_NORMAL,
#ifdef?CONFIG_HIGHMEM
?/*
??*?A?memory?area?that?is?only?addressable?by?the?kernel?through
??*?mapping?portions?into?its?own?address?space.?This?is?for?example
??*?used?by?i386?to?allow?the?kernel?to?address?the?memory?beyond
??*?900MB.?The?kernel?will?set?up?special?mappings?(page
??*?table?entries?on?i386)?for?each?page?that?the?kernel?needs?to
??*?access.
??*/
?/*高端內存區域:
?此區域是32位時代的產物,內核和用戶地址空間按1:3劃分,
?內核地址空間只有1GB,不能把1GB以上內存直接映射到該地址*/
?ZONE_HIGHMEM,
#endif
?/*可移動區域:
?它是一個偽內存區域,用來防止內存碎片*/
?ZONE_MOVABLE,
#ifdef?CONFIG_ZONE_DEVICE
?/*設備區域:
?為支持持久內存熱插拔增加的內存區域,每一個內存區域用一個zone結構體來描述*/
?ZONE_DEVICE,
#endif
?__MAX_NR_ZONES
};
每個內存區域使用一個zone結構體描述,如下為主要成員:
structzone{
/*Read-mostlyfields*/
/*zonewatermarks,accesswith*_wmark_pages(zone)macros*/
unsignedlongwatermark[NR_WMARK];//頁分配器使用的水線
unsignedlongnr_reserved_highatomic;
/*
*Wedon'tknowifthememorythatwe'regoingtoallocatewillbe
*freeableor/anditwillbereleasedeventually,sotoavoidtotally
*wastingseveralGBoframwemustreservesomeofthelowerzone
*memory(otherwisewerisktorunOOMonthelowerzonesdespite
*therebeingtonsoffreeableramonthehigherzones).Thisarrayis
*recalculatedatruntimeifthesysctl_lowmem_reserve_ratiosysctl
*changes.
*/
longlowmem_reserve[MAX_NR_ZONES];//頁分配器使用,當前區域保留多少頁不能借給高的區域類型
#ifdefCONFIG_NUMA
intnode;
#endif
/*
*ThetargetratioofACTIVE_ANONtoINACTIVE_ANONpageson
*thiszone'sLRU.Maintainedbythepageoutcode.
*/
unsignedintinactive_ratio;
structpglist_data*zone_pgdat;//指向內存節點的pglist_data實例
structper_cpu_pageset__percpu*pageset;//每處理頁集合
/*
*Thisisaper-zonereserveofpagesthatshouldnotbe
*considereddirtyablememory.
*/
unsignedlongdirty_balance_reserve;
#ifndefCONFIG_SPARSEMEM
/*
*Flagsforapageblock_nr_pagesblock.Seepageblock-flags.h.
*InSPARSEMEM,thismapisstoredinstructmem_section
*/
unsignedlong*pageblock_flags;
#endif/*CONFIG_SPARSEMEM*/
#ifdefCONFIG_NUMA
/*
*zonereclaimbecomesactiveifmoreunmappedpagesexist.
*/
unsignedlongmin_unmapped_pages;
unsignedlongmin_slab_pages;
#endif/*CONFIG_NUMA*/
/*zone_start_pfn==zone_start_paddr>>PAGE_SHIFT*/
unsignedlongzone_start_pfn;//當前區域的起始物理頁號
/*
*spanned_pagesisthetotalpagesspannedbythezone,including
*holes,whichiscalculatedas:
*spanned_pages=zone_end_pfn-zone_start_pfn;
*
*present_pagesisphysicalpagesexistingwithinthezone,which
*iscalculatedas:
*present_pages=spanned_pages-absent_pages(pagesinholes);
*
*managed_pagesispresentpagesmanagedbythebuddysystem,which
*iscalculatedas(reserved_pagesincludespagesallocatedbythe
*bootmemallocator):
*managed_pages=present_pages-reserved_pages;
*
*Sopresent_pagesmaybeusedbymemoryhotplugormemorypower
*managementlogictofigureoutunmanagedpagesbychecking
*(present_pages-managed_pages).Andmanaged_pagesshouldbeused
*bypageallocatorandvmscannertocalculateallkindsofwatermarks
*andthresholds.
*
*Lockingrules:
*
*zone_start_pfnandspanned_pagesareprotectedbyspan_seqlock.
*Itisaseqlockbecauseithastobereadoutsideofzone->lock,
*anditisdoneinthemainallocatorpath.But,itiswritten
*quiteinfrequently.
*
*Thespan_seqlockisdeclaredalongwithzone->lockbecauseitis
*frequentlyreadinproximitytozone->lock.It'sgoodto
*givethemachanceofbeinginthesamecacheline.
*
*Writeaccesstopresent_pagesatruntimeshouldbeprotectedby
*mem_hotplug_begin/end().Anyreaderwhocan'ttolerantdriftof
*present_pagesshouldget_online_mems()togetastablevalue.
*
*Readaccesstomanaged_pagesshouldbesafebecauseit'sunsigned
*long.Writeaccesstozone->managed_pagesandtotalram_pagesare
*protectedbymanaged_page_count_lockatruntime.Idealyonly
*adjust_managed_page_count()shouldbeusedinsteadofdirectly
*touchingzone->managed_pagesandtotalram_pages.
*/
unsignedlongmanaged_pages;//伙伴分配器管理的物理頁的數量
unsignedlongspanned_pages;//當前區域跨越的總頁數,包括空洞
unsignedlongpresent_pages;//當前區域存在的物理頁的數量,不包括空洞
constchar*name;//區域名稱
#ifdefCONFIG_MEMORY_ISOLATION
/*
*Numberofisolatedpageblock.Itisusedtosolveincorrect
*freepagecountingproblemduetoracyretrievingmigratetype
*ofpageblock.Protectedbyzone->lock.
*/
unsignedlongnr_isolate_pageblock;
#endif
#ifdefCONFIG_MEMORY_HOTPLUG
/*seespanned/present_pagesformoredescription*/
seqlock_tspan_seqlock;
#endif
/*
*wait_table--thearrayholdingthehashtable
*wait_table_hash_nr_entries--thesizeofthehashtablearray
*wait_table_bits--wait_table_size==(1<
3.3 物理頁
頁是內存管理當中最小單位,頁面中的內存其物理地址是連續的,每個物理頁由struct page描述。為了節省內存,struct page是個聯合體。
頁,又稱為頁幀,在內核當中,內存管理單元MMU(負責虛擬地址和物理地址轉換的硬件)是把物理頁page作為內存管理的基本單位。體系結構不同,支持的頁大小也不同。(32位體系結構支持4KB的頁、64位體系結構支持8KB的頁、MIPS64架構體系支持16KB的頁)

審核編輯:湯梓紅
-
ARM
+關注
關注
135文章
9552瀏覽量
391845 -
內核
+關注
關注
4文章
1467瀏覽量
42872 -
Linux
+關注
關注
88文章
11758瀏覽量
219009 -
物理內存
+關注
關注
0文章
11瀏覽量
8653 -
虛擬內存
+關注
關注
0文章
79瀏覽量
8456
原文標題:Linux內核 | 物理內存組織結構
文章出處:【微信號:嵌入式開發AIoT,微信公眾號:嵌入式開發AIoT】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
一文詳解Linux內核源碼組織結構
走進Linux內存系統探尋內存管理的機制和奧秘
Linux內存相關知識科普
Linux內核地址映射模型與Linux內核高端內存詳解
帶你了解Linux內核體系結構
Linux內核結構詳解
Linux0.11-內存組織和進程結構
STM32MP157 Linux系統移植開發篇7:Linux內核目錄結構詳解
Linux內核之物理內存組織結構
評論