日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux mmu的实现的讲解_Linux中的物理内存管理 [一]

發(fā)布時(shí)間:2025/3/20 linux 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux mmu的实现的讲解_Linux中的物理内存管理 [一] 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前面的文章介紹了Linux中虛擬地址空間的管理,本文將討論Linux系統(tǒng)對物理內(nèi)存的管理。

NUMA

所謂物理內(nèi)存,就是安裝在機(jī)器上的,實(shí)打?qū)嵉膬?nèi)存設(shè)備(不包括硬件cache),被CPU通過總線訪問。在多核系統(tǒng)中,如果物理內(nèi)存對所有CPU來說沒有區(qū)別,每個(gè)CPU訪問內(nèi)存的方式也一樣,則這種體系結(jié)構(gòu)被稱為Uniform Memory Access(UMA)。

如果物理內(nèi)存是分布式的,由多個(gè)cell組成(比如每個(gè)核有自己的本地內(nèi)存),那么CPU在訪問靠近它的本地內(nèi)存的時(shí)候就比較快,訪問其他CPU的內(nèi)存或者全局內(nèi)存的時(shí)候就比較慢,這種體系結(jié)構(gòu)被稱為Non-Uniform Memory Access(NUMA)。

以上是硬件層面上的NUMA,而作為軟件層面的Linux,則對NUMA的概念進(jìn)行了抽象。即便硬件上是一整塊連續(xù)內(nèi)存的UMA,Linux也可將其劃分為若干的node。同樣,即便硬件上是物理內(nèi)存不連續(xù)的NUMA,Linux也可將其視作UMA。

所以,在Linux系統(tǒng)中,你可以基于一個(gè)UMA的平臺測試NUMA上的應(yīng)用特性。從另一個(gè)角度,UMA就是只有一個(gè)node的特殊NUMA,所以兩者可以統(tǒng)一用NUMA模型表示。

在NUMA系統(tǒng)中,當(dāng)Linux內(nèi)核收到內(nèi)存分配的請求時(shí),它會優(yōu)先從發(fā)出請求的CPU本地或鄰近的內(nèi)存node中尋找空閑內(nèi)存,這種方式被稱作local allocation,local allocation能讓接下來的內(nèi)存訪問相對底層的物理資源是local的。

每個(gè)node由一個(gè)或多個(gè)zone組成(我們可能經(jīng)常在各種對虛擬內(nèi)存和物理內(nèi)存的描述中迷失,但以后你見到zone,就知道指的是物理內(nèi)存),每個(gè)zone又由若干page frames組成(一般page frame都是指物理頁面)。

Page Frame

雖然內(nèi)存訪問的最小單位是byte或者word,但MMU是以page為單位來查找頁表的,page也就成了Linux中內(nèi)存管理的重要單位。包括換出(swap out)、回收(relcaim)、映射等操作,都是以page為粒度的。

因此,描述page frame的struct page自然成為了內(nèi)核中一個(gè)使用頻率極高,非常重要的結(jié)構(gòu)體,來看下它是怎樣構(gòu)成的(為了講解需要并非最新內(nèi)核代碼):

struct page {unsigned long flags;atomic_t count; atomic_t _mapcount; struct list_head lru;struct address_space *mapping;unsigned long index; ... }
  • flags表示page frame的狀態(tài)或者屬性,包括和內(nèi)存回收相關(guān)的PG_active, PG_dirty, PG_writeback, PG_reserved, PG_locked, PG_highmem等。其實(shí)flags是身兼多職的,它還有其他用途,這將在下文中介紹到。
  • count表示引用計(jì)數(shù)。當(dāng)count值為0時(shí),該page frame可被free掉;如果不為0,說明該page正在被某個(gè)進(jìn)程或者內(nèi)核使用,調(diào)用page_count()可獲得count值。
  • _mapcount表示該page frame被映射的個(gè)數(shù),也就是多少個(gè)page table entry中含有這個(gè)page frame的PFN。
  • lru是"least recently used"的縮寫,根據(jù)page frame的活躍程度(使用頻率),一個(gè)可回收的page frame要么掛在active_list雙向鏈表上,要么掛在inactive_list雙向鏈表上,以作為頁面回收的選擇依據(jù),lru中包含的就是指向所在鏈表中前后節(jié)點(diǎn)的指針(參考這篇文章)。
  • 如果一個(gè)page是屬于某個(gè)文件的(也就是在page cache中),則mapping指向文件inode對應(yīng)的address_space(這個(gè)結(jié)構(gòu)體雖然叫address_space,但并不是進(jìn)程地址空間里的那個(gè)address space),index表示該page在文件內(nèi)的offset(以page size為單位)。

有了文件的inode和index,當(dāng)這個(gè)page的內(nèi)容需要和外部disk/flash上對應(yīng)的部分同步時(shí),才可以找到具體的文件位置。如果一個(gè)page是anonymous的,則mapping指向表示swap cache的swapper_space,此時(shí)index就是swapper_space內(nèi)的offset。

事實(shí)上,現(xiàn)在最新Linux版本的struct page實(shí)現(xiàn)中大量用到了union,也就是同一個(gè)元素在不同的場景下有不同的意義。這是因?yàn)槊總€(gè)page frame都需要一個(gè)struct page來描述,一個(gè)page frame占4KB,一個(gè)struct page占32字節(jié),那所有的struct page需要消耗的內(nèi)存占了整個(gè)系統(tǒng)內(nèi)存的32/4096,不到1%的樣子,說小也小,但一個(gè)擁有4GB物理內(nèi)存的系統(tǒng),光這一項(xiàng)的開銷最大就可達(dá)30多MB。

如果能在struct page里省下4個(gè)字節(jié),那就能省下4多MB的內(nèi)存空間,所以這個(gè)結(jié)構(gòu)體的設(shè)計(jì)必須非常考究,不能因?yàn)槎嘁环N場景的需要就在struct page中增加一個(gè)元素,而是應(yīng)該盡量采取復(fù)用的方式。

需要注意的是,struct page描述和管理的是這4KB的物理內(nèi)存,它并不關(guān)注這段內(nèi)存中的數(shù)據(jù)變化。

Zone

因?yàn)橛布南拗?#xff0c;內(nèi)核不能對所有的page frames采用同樣的處理方法,因此它將屬性相同的page frames歸到一個(gè)zone中。對zone的劃分與硬件相關(guān),對不同的處理器架構(gòu)是可能不一樣的。

比如在i386中,一些使用DMA的設(shè)備只能訪問0~16MB的物理空間,因此將0~16MB劃分為了ZONE_DMA。ZONE_HIGHMEM則是適用于要訪問的物理地址空間大于虛擬地址空間,不能建立直接映射的場景。除開這兩個(gè)特殊的zone,物理內(nèi)存中剩余的部分就是ZONE_NORMAL了。

在其他一些處理器架構(gòu)中,ZONE_DMA可能是不需要的,

ZONE_HIGHMEM也可能沒有。比如在64位的x64中,因?yàn)閮?nèi)核虛擬地址空間足夠大,不再需要ZONE_HIGH映射,但為了區(qū)分使用32位地址的DMA應(yīng)用和使用64位地址的DMA應(yīng)用,64位系統(tǒng)中設(shè)置了ZONE_DMA32和ZONE_DMA。

所以,同樣的ZONE_DMA,對于32位系統(tǒng)和64位系統(tǒng)表達(dá)的意義是不同的,ZONE_DMA32則只對64位系統(tǒng)有意義,對32位系統(tǒng)就等同于ZONE_DMA,沒有單獨(dú)存在的意義。

此外,還有防止內(nèi)存碎片化的ZONE_MOVABLE和支持設(shè)備熱插拔的ZONE_DEVICE。可通過“cat /proc/zoneinfo |grep Node”命令查看系統(tǒng)中包含的zones的種類。

Zone雖然是用于管理物理內(nèi)存的,但zone與zone之間并沒有任何的物理分割,它只是Linux為了便于管理進(jìn)行的一種邏輯意義上的劃分。Zone在Linux中用struct zone表示(以下為了講解需要,調(diào)整了結(jié)構(gòu)體中元素的順序):

struct zone {spinlock_t lock;unsigned long spanned_pages;unsigned long present_pages; unsigned long nr_reserved_highatomic; atomic_long_t managed_pages;struct free_area free_area[MAX_ORDER];unsigned long _watermark[NR_WMARK];long lowmem_reserve[MAX_NR_ZONES];atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];unsigned long zone_start_pfn;struct pglist_data *zone_pgdat;struct page *zone_mem_map;... }
  • lock是用來防止并行訪問struct zone的spin lock,它只能保護(hù)struct zone這個(gè)結(jié)構(gòu)體哈,可不能保護(hù)整個(gè)zone里的所有pages。
  • spanned_pages是這個(gè)zone含有的總的page frames數(shù)目。在某些體系結(jié)構(gòu)(比如Sparc)中,zone中可能存在沒有物理頁面的"holes",spanned_pages減去這些holes里的absent pages就是present_pages。

nr_reserved_highatomic是為某些場景預(yù)留的內(nèi)存(參考本系列的第三篇文章),managed_pages是由buddy內(nèi)存分配系統(tǒng)管理的page frames數(shù)目,其實(shí)也就是present_pages減去reserved pages。

  • free_area由free list空閑鏈表構(gòu)成,表示zone中還有多少空余可供分配的page frames。_watermark有min(mininum), low, high三種,可作為啟動內(nèi)存回收的判斷標(biāo)準(zhǔn)(詳情請參考這篇文章)。

lowmem_reserve是給更高位的zones預(yù)留的內(nèi)存(更詳細(xì)的介紹請參考這篇文章)。vm_stat作為zone的內(nèi)存使用情況的統(tǒng)計(jì)信息,是“/proc/zoneinfo”的數(shù)據(jù)來源。

  • zone_start_pfn是zone的起始物理頁面號,zone_start_pfn+spanned_pages就是該zone的結(jié)束物理頁面號。zone_pgdat是指向這個(gè)zone所屬的node的。zone_mem_map指向由struct page構(gòu)成的mem_map數(shù)組。

因?yàn)閮?nèi)核對zone的訪問是很頻繁的,為了更好的利用硬件cache來提高訪問速度,struct zone中還有一些填充位,用于幫助結(jié)構(gòu)體元素的cache line對齊。這和struct page對內(nèi)存精打細(xì)算的使用形成了鮮明的對比,因?yàn)閦one的種類很有限,一個(gè)系統(tǒng)中一共也不會有多少個(gè)zones,struct zone這個(gè)結(jié)構(gòu)體的體積大點(diǎn)也沒有什么關(guān)系。

關(guān)于前面提到的node的介紹,請看下文分解。

原創(chuàng)文章,轉(zhuǎn)載請注明出處。

總結(jié)

以上是生活随笔為你收集整理的linux mmu的实现的讲解_Linux中的物理内存管理 [一]的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。