記憶體分配掩碼

記憶體分配掩碼

記憶體分配掩碼(Get Free Page Mask, GFP_mask),是描述核心分配記憶體方法的32位或64位標誌符,可分為兩類:行為修飾符、區修飾符。行為描述符表示分配方式,區修飾符表示分配區。

基本介紹

  • 中文名:記憶體分配掩碼
  • 外文名:Get Free Page Mask
  • 定義:核心記憶體分配方式
  • 系統:Linux
  • 簡寫:GFP_mask
  • 套用學科:計算機科學
定義,區修飾符,行為修飾符,類型標誌,

定義

核心函式kmallocvmalloc在分配記憶體時都會用到記憶體分配掩碼,在核心源碼linux4.20版本中,記憶體分配掩碼位於linux\include\linux\gfp.h,具體定義如下。
#define ___GFP_DMA           0x01u#define ___GFP_HIGHMEM       0x02u#define ___GFP_DMA32              0x04u#define ___GFP_MOVABLE        0x08u#define ___GFP_RECLAIMABLE      0x10u#define ___GFP_HIGH          0x20u#define ___GFP_IO         0x40u#define ___GFP_FS        0x80u#define ___GFP_WRITE              0x100u#define ___GFP_NOWARN          0x200u#define ___GFP_RETRY_MAYFAIL  0x400u#define ___GFP_NOFAIL             0x800u#define ___GFP_NORETRY         0x1000u#define ___GFP_MEMALLOC           0x2000u#define ___GFP_COMP         0x4000u#define ___GFP_ZERO          0x8000u#define ___GFP_NOMEMALLOC      0x10000u#define ___GFP_HARDWALL            0x20000u#define ___GFP_THISNODE              0x40000u#define ___GFP_ATOMIC            0x80000u#define ___GFP_ACCOUNT        0x100000u#define ___GFP_DIRECT_RECLAIM       0x200000u#define ___GFP_KSWAPD_RECLAIM      0x400000u
上述標誌主要分為兩類:行為描述符和區修飾符,布局如下圖所示。
記憶體分配掩碼布局圖記憶體分配掩碼布局圖

區修飾符

區修飾符表示記憶體應該從哪個區分配,通常分配可以從任何區開始,不過,核心優先從ZONE_NORMAL開始,這樣可確保其他區在需要時有足夠的空閒頁可用。下表是區修飾符的列表。
標誌描述
__GFP_DMA
從ZONE_DMA分配
__GFP_DMA32
只在ZONE_DMA32分配
__GFP_HIGHMEM
從ZONE_HIGHMEM或ZONE_NORMAL分配
指定以上標誌中的一個就可以改變核心試圖進行分配的區,不能給__get_free_pages()或kmalloc執行ZONE_HIGHMEM,因為這兩個函式返回的都是邏輯地址,而不是page結構,這兩個函式分配的記憶體當前有可能還沒有映射到核心的虛擬地址空間,因此可能沒有邏輯地址。
行為修飾符描述
__GFP_RECLAIMABLE
__GFP_MOVABLE
是頁遷移機制所需的標誌,它們分別將分配的記憶體標記為可回收的或可移動的。
__GFP_HIGH
分配器可以訪問緊急事件緩衝池
__GFP_IO
在查找空閒記憶體期間,分配器可以進行磁碟I/O操作。
__GFP_FS
分配器可執行VFS操作,可啟動檔案系統I/O。
__GFP_REPEAT
分配器在分配失敗後自動重試,重試也可能失敗,但有上限次數。
__GFP_NOFAIL
分配器在分配失敗後一直重試,直至成功
__GFP_NORETRY
分配器在分配失敗後不重試,從而導致分配失敗
__GFP_COMP
添加混合頁元素, 在hugetlb的代碼內部使用
__GFP_ZERO
分配器在分配成功時,將返回填充位元組0的頁

行為修飾符

行為修飾符表示核心應當如何分配所需的記憶體,例如分配器分配記憶體中的睡眠行為、失敗行為、啟動各類設備檔案行為,具體含義如下表。

類型標誌

在源碼中注釋強調,一般不直接使用行為修飾符,而是採用類型標誌組合行為修飾符和區修飾符,將各種可能用到的組合進行組合,用戶使用時無需記住各類行為修飾符的意義,而是直接使用下述表格中的類型標誌。
類型標誌描述
GFP_ATOMIC
用於原子分配,在任何情況下都不能中斷,用在中斷處理程式,下半部,持有自旋鎖以及其他不能睡眠的地方
GFP_NOWAIT
與GFP_ATOMIC類似,不同之處在於,調用不會退給緊急記憶體池,這就增加了記憶體分配失敗的可能性
GFP_KERNEL
這是一種常規的分配方式,可能會阻塞。這個標誌在睡眠安全時用在進程的長下文代碼中。為了獲取調用者所需的記憶體,核心會盡力而為。這個標誌應該是首選標誌
GFP_NOIO
這種分配可以阻塞,但不會啟動磁碟I/O,這個標誌在不能引發更多的磁碟I/O時阻塞I/O代碼,這可能導致令人不愉快的遞歸
GFP_NOFS
這種分配在必要時可以阻塞,但是也可能啟動磁碟,但是不會啟動檔案系統操作,這個標誌在你不能在啟動另一個檔案系統操作時,用在檔案系統部分的代碼中
GFP_USER
這是一種常規的分配方式,可能會阻塞。這個標誌用於為用戶空間進程分配記憶體時使用
GFP_DMA GFP_DMA32
用於分配適用於DMA的記憶體,當前是__GFP_DMA的同義詞,GFP_DMA32也是__GFP_GMA32的同義詞
GFP_HIGHUSER
是GFP_USER的一個擴展,也用於用戶空間。 它允許分配無法直接映射的高端記憶體。使用高端記憶體頁是沒有壞處的,因為用戶過程的地址空間總是通過非線性頁表組織的
GFP_HIGHUSER_MOVABLE
用途類似於GFP_HIGHUSER,但分配將從虛擬記憶體域ZONE_MOVABLE進行
其在源碼中的表現方式為各類區描述符和行為描述符的組合,如下
#define __GFP_DMA   ((__force gfp_t)___GFP_DMA)#define GFP_ATOMIC (__GFP_HIGH|__GFP_ATOMIC|__GFP_KSWAPD_RECLAIM)#define GFP_KERNEL (__GFP_RECLAIM | __GFP_IO | __GFP_FS)#define GFP_NOWAIT (__GFP_KSWAPD_RECLAIM)#define GFP_NOIO      (__GFP_RECLAIM)#define GFP_NOFS     (__GFP_RECLAIM | __GFP_IO)#define GFP_USER     (__GFP_RECLAIM|__GFP_IO|__GFP_FS| __GFP_HARDWALL)#define GFP_DMA             __GFP_DMA#define GFP_DMA32        __GFP_DMA32#define GFP_HIGHUSER   (GFP_USER | __GFP_HIGHMEM)

相關詞條

熱門詞條

聯絡我們