對於ZONE MOVABLE的理解

2021-09-09 06:30:06 字數 3629 閱讀 5541

linux記憶體管理子系統把記憶體劃分為不同zone,本文主要來介紹下其中的乙個:zone_movable。我在網上看到一些文章經常會把它叫做虛擬記憶體區(pseudo zone),為什麼說它是乙個虛擬記憶體區呢?實際上它是從平台中最高記憶體區中(比如zone_hihgmem)劃出了一部分記憶體,作為zone_movable。核心中有如下**可以作為參考依據:

static

void __init find_usable_zone_for_movable

(void

)vm_bug_on

(zone_index ==-1

);movable_zone = zone_index;

}

那麼引入該記憶體區的目的是什麼?

它存在的意義實際上是為了減少記憶體的碎片化,想象一下這個場景,當我們需要一塊大的連續記憶體時向夥伴系統申請,雖然對應的記憶體區剩餘記憶體還很多,但是卻發現對應的記憶體區並無法滿足連續的記憶體申請需求,這就是由於記憶體碎片化導致的問題。那麼此時是可以通過記憶體遷移來完成連續記憶體的申請,但是這個過程並不一定能夠成功,因為中間有一些頁面可能是不允許遷移的。

引入zone_movable就是為了優化記憶體遷移場景的,主要目的是想要把non-movable和movable的記憶體區分管理,當我們劃分出該區域後,那麼只有可遷移的頁才能夠從該區域申請,這樣當我們後面**記憶體時,針對該區域就都可以執行遷移,從而保證能夠獲取到足夠大的連續記憶體。

除了這個用途之外,該區域還有一種使用場景,那就是memory hotplug場景,記憶體熱插拔場景,當我們對記憶體區執行remove時,必須保證其中的內容都是可以被遷移走的,因此熱插拔的記憶體區必須位於zone_movable區域。

enum zone_type 

;

簡單來說,可遷移的頁面不一定都在zone_movable中,但是zone_movable中的頁面必須都是可遷移的。

我們通過檢視/proc/pagetypeinfo的返回資訊可以看到在movable zone中不存在unmovable型別的頁面,只有movable型別的頁面。

這個管理區域存放的page都是可遷移的,只能被帶有__gfp_highmem和__gfp_movable標誌的記憶體申請所使用,比如:

#define gfp_highuser_movable    (gfp_highuser | __gfp_movable)

#define gfp_user (__gfp_wait | __gfp_io | __gfp_fs | __gfp_hardwall)

#define gfp_highuser (gfp_user | __gfp_highmem)

主要注意的是不要把分配標誌__gfp_movable和管理區zone_movable混淆,兩者並不是對應的關係。

#define __gfp_dma   ((__force gfp_t)___gfp_dma)

#define __gfp_highmem ((__force gfp_t)___gfp_highmem)

#define __gfp_dma32 ((__force gfp_t)___gfp_dma32)

#define __gfp_movable ((__force gfp_t)___gfp_movable) /* page is movable */

#define gfp_zonemask (__gfp_dma|__gfp_highmem|__gfp_dma32|__gfp_movable)

這幾個分配標誌被稱為zone modifiers,他們用來標識優先從哪個zone分配記憶體。

bit       result

***************==

0x0 => normal

0x1 => dma or normal

0x2 => highmem or normal

0x3 => bad (dma+highmem)

0x4 => dma32 or dma or normal

0x5 => bad (dma+dma32)

0x6 => bad (highmem+dma32)

0x7 => bad (highmem+dma32+dma)

0x8 => normal (movable+0)

0x9 => dma or normal (movable+dma)

0xa => movable (movable is valid only if highmem is set too)

0xb => bad (movable+highmem+dma)

0xc => dma32 (movable+dma32)

0xd => bad (movable+dma32+dma)

0xe => bad (movable+dma32+highmem)

0xf => bad (movable+dma32+highmem+dma)

一共有4個bit用來表示組合型別,其中低3個bit只能選擇乙個(__gfp_dma/__gfp_highmem/__gfp_dma32),而__gfp_movable可以和其他三種的任何乙個組合使用,因此一共有16中組合,根據各種型別進行乙個偏移存放到乙個long型別table中。

gfp_zone_table:

|bad|bad|bad|dma32|bad|movable|......|normal|

這些結果會根據上面的bit組合值做乙個偏移,存放到zone table中,從而可以根據組合快速定位要使用的zone管理區。由上可見,__gfp_movable代表的是一種分配策略,並不是和zone_movable匹配的,上一節也做了介紹,必須是(__gfp_highmem和__gfp_movable)同時置位才會從zone_movable管理區去分配記憶體。

the zone fallback order is movable=>highmem=>normal=>dma32=>dma
因此我們分配記憶體時並不一定就會按照傳入的flag來進行分配,如果對應zone中沒有符合要求的記憶體,那麼會依次進行fallback查詢符合要求的記憶體。

可以通過傳入不同的cmdline來設定:

比如kernelcore=yyyy和movablecore=zzzz分別表示不同的含義:

1) when kernelcore=yyyy boot option is used,

size of memory not for movable pages (not for offline) is yyyy.

size of memory for movable pages (for offline) is total-yyyy.

2) when movablecore=zzzz boot option is used,

size of memory not for movable pages (not for offline) is total - zzzz.

size of memory for movable pages (for offline) is zzzz.

對於while if foeach 等迴圈的理解

一,for i 1 i 5 i 此串 會出現死迴圈,在while迴圈裡當程式執行到echo 1 時會再返回while 繼續執行迴圈。因此出現死迴圈。解決方法在echo1 後邊加上 i 以此不滿足while的條件條件跳出迴圈。while迴圈條只給乙個永遠為真的條件,就會永遠迴圈下去。如while 1 ...

對於Python中RawString的理解

1 作用 可以表示 多行注釋 多行字串 其內的單雙引號不轉義 2 r 代表的意思是 raw 3 r 只對其內的反斜槓起作用 注意單個 的問題 raw string 有什麼用處呢?raw string 就是會自動將反斜槓轉義。print n print r n n 注 出現了兩個空行是因為 print...

對於Python中RawString的理解

1 作用 可以表示 多行注釋 多行字串 其內的單雙引號不轉義 2 r 代表的意思是 raw 3 r 只對其內的反斜槓起作用 注意單個 的問題 raw string 有什麼用處呢?raw string 就是會自動將反斜槓轉義。print n print r n n 注 出現了兩個空行是因為 print...