背景
经常在看内存管理这块的代码时会看到这两个标记,有时候稍微不注意就会把他们搞混了,本篇博客就来聊聊他们的区别。
定义
首先这两个标记的定义如下,由此可见他们两个是不同的两个标记,表示的当然也是不同的意义:
#define ___GFP_HIGH 0x20u
#define ___GFP_HIGHMEM 0x02u
对于___GFP_HIGHMEM 标记来说,它是用来在内存申请时确定要从哪个目标zone中申请内存的。具体可以参考我的博文:
《如何从GFP确定最后申请的内存来自哪个zone?》
那么对于___GFP_HIGH 这个标记来说,申请内存时传入该标记的意义在于申请内存时,选择更加激进的策略来申请。
使用原理
我们看下它的原理,内存申请时需要传递alloc_flags,这个标志alloc_flags是从gfp_mask转换而来的:
2826 static inline int
2827 gfp_to_alloc_flags(gfp_t gfp_mask)
2828 {
2829 int alloc_flags = ALLOC_WMARK_MIN | ALLOC_CPUSET;
2830 const bool atomic = !(gfp_mask & (__GFP_WAIT | __GFP_NO_KSWAPD));
2831
2832 /* __GFP_HIGH is assumed to be the same as ALLOC_HIGH to save a branch. */
2833 BUILD_BUG_ON(__GFP_HIGH != (__force gfp_t) ALLOC_HIGH);
2834
2835 /*
2836 * The caller may dip into page reserves a bit more if the caller
2837 * cannot run direct reclaim, or if the caller has realtime scheduling
2838 * policy or is asking for __GFP_HIGH memory. GFP_ATOMIC requests will
2839 * set both ALLOC_HARDER (atomic == true) and ALLOC_HIGH (__GFP_HIGH).
2840 */
2841 alloc_flags |= (__force int) (gfp_mask & __GFP_HIGH);
2842
...
可以看到alloc_flags |= (__force int) (gfp_mask & __GFP_HIGH); 这一条就是设置ALLOC_HIGH申请标志的,因为ALLOC_HIGH和__GFP_HIGH的定义值是相等的:
#define ALLOC_HIGH 0x20 /* __GFP_HIGH set */
设置了这个alloc_flags,在哪里生效呢?也就是在申请内存时选择了特定的zone,在判断该zone的剩余空闲内存是否允许被申请时做判断使用的:
*/
2079 static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark,
2080 int classzone_idx, int alloc_flags, long free_pages)
2081 {
2082 /* free_pages my go negative - that's OK */
2083 long min = mark;
2084 long lowmem_reserve = z->lowmem_reserve[classzone_idx];
2085 int o;
2086 long free_cma = 0;
2087
2088 free_pages -= (1 << order) - 1;
2089 if (alloc_flags & ALLOC_HIGH)
2090 min -= min / 2;
2091 if (alloc_flags & ALLOC_HARDER)
2092 min -= min / 4;
2093 #ifdef CONFIG_CMA
2094 /* If allocation can't use CMA areas don't use free CMA pages */
2095 if (!(alloc_flags & ALLOC_CMA))
2096 free_cma = zone_page_state(z, NR_FREE_CMA_PAGES);
2097 #endif
2098
2099 if (free_pages - free_cma <= min + lowmem_reserve)
2100 return false;
截取部分关键代码,这里在判断zone中是否有足够空闲内存时,在计算预留内存水位时会根据此申请标记为来做修改,当标记位存在时,水位值会修改为当前的一半再去判断,也就是说预留内存更少了,那么只要free大于预留内存(min + lowmem_reserve)就可以申请到内存。因而简单的换一种说法就是,当使用___GFP_HIGH申请内存时,将会更加容易申请到。