記憶體分配掩碼(Get Free Page Mask, GFP_mask),是描述核心分配記憶體方法的32位或64位標誌符,可分為兩類:行為修飾符、區修飾符。行為描述符表示分配方式,區修飾符表示分配區。
基本介紹
- 中文名:記憶體分配掩碼
- 外文名:Get Free Page Mask
- 定義:核心記憶體分配方式
- 系統:Linux
- 簡寫:GFP_mask
- 套用學科:計算機科學
定義,區修飾符,行為修飾符,類型標誌,
定義
#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)