如何理解内存管理中的alloc_flags?

2023-10-07 07:38
文章标签 内存 理解 管理 alloc flags

本文主要是介绍如何理解内存管理中的alloc_flags?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先需要明确一点alloc_flags和gfp_mask之间的区别,gfp_mask是使用alloc_pages申请内存时所传递的申请标记,而alloc_flags是在内存管理子系统内部使用的另一个标记,二者是不同的,当然alloc_flags也是从gfp_mask经过计算得到的。

关于alloc_flags的定义有如下几个:

/* The ALLOC_WMARK bits are used as an index to zone->watermark */
#define ALLOC_WMARK_MIN     WMARK_MIN
#define ALLOC_WMARK_LOW     WMARK_LOW
#define ALLOC_WMARK_HIGH    WMARK_HIGH
#define ALLOC_NO_WATERMARKS 0x04 /* don't check watermarks at all */#define ALLOC_HARDER        0x10 /* try to alloc harder */
#define ALLOC_HIGH      0x20 /* __GFP_HIGH set */
#define ALLOC_CPUSET        0x40 /* check for correct cpuset */                                                                                                                                      
#define ALLOC_CMA       0x80 /* allow allocations from CMA areas */
#define ALLOC_FAIR      0x100 /* fair zone allocation */

那么获取alloc_flags的地方就是在gfp_to_alloc_flags中:

static inline int
gfp_to_alloc_flags(gfp_t gfp_mask)
{int alloc_flags = ALLOC_WMARK_MIN | ALLOC_CPUSET;const bool atomic = !(gfp_mask & (__GFP_WAIT | __GFP_NO_KSWAPD));/* __GFP_HIGH is assumed to be the same as ALLOC_HIGH to save a branch. */BUILD_BUG_ON(__GFP_HIGH != (__force gfp_t) ALLOC_HIGH);/*   * The caller may dip into page reserves a bit more if the caller* cannot run direct reclaim, or if the caller has realtime scheduling* policy or is asking for __GFP_HIGH memory.  GFP_ATOMIC requests will* set both ALLOC_HARDER (atomic == true) and ALLOC_HIGH (__GFP_HIGH).*/alloc_flags |= (__force int) (gfp_mask & __GFP_HIGH);if (atomic) {/*   * Not worth trying to allocate harder for __GFP_NOMEMALLOC even* if it can't schedule.*/if (!(gfp_mask & __GFP_NOMEMALLOC))alloc_flags |= ALLOC_HARDER;/*   * Ignore cpuset mems for GFP_ATOMIC rather than fail, see the* comment for __cpuset_node_allowed_softwall().*/alloc_flags &= ~ALLOC_CPUSET;} else if (unlikely(rt_task(current)) && !in_interrupt())alloc_flags |= ALLOC_HARDER;if (likely(!(gfp_mask & __GFP_NOMEMALLOC))) {if (gfp_mask & __GFP_MEMALLOC)alloc_flags |= ALLOC_NO_WATERMARKS;else if (in_serving_softirq() && (current->flags & PF_MEMALLOC))alloc_flags |= ALLOC_NO_WATERMARKS;else if (!in_interrupt() &&((current->flags & PF_MEMALLOC) ||unlikely(test_thread_flag(TIF_MEMDIE))))alloc_flags |= ALLOC_NO_WATERMARKS;}    
#ifdef CONFIG_CMAif (allocflags_to_migratetype(gfp_mask) == MIGRATE_MOVABLE)alloc_flags |= ALLOC_CMA;
#endifreturn alloc_flags;
}                                      

这里我主要讲解ALLOC_HARDER和ALLOC_HIGH,这两个标记都是用来表示在申请内存时判断zone中是否存在合适的内存做判断使用的。

static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark,                                                                                                                       int classzone_idx, int alloc_flags, long free_pages)
{/* free_pages my go negative - that's OK */long min = mark;long lowmem_reserve = z->lowmem_reserve[classzone_idx];int o;long free_cma = 0;free_pages -= (1 << order) - 1;if (alloc_flags & ALLOC_HIGH)min -= min / 2;if (alloc_flags & ALLOC_HARDER)min -= min / 4;
#ifdef CONFIG_CMA/* If allocation can't use CMA areas don't use free CMA pages */if (!(alloc_flags & ALLOC_CMA))free_cma = zone_page_state(z, NR_FREE_CMA_PAGES);
#endifif (free_pages - free_cma <= min + lowmem_reserve)return false;for (o = 0; o < order; o++) {/* At the next order, this order's pages become unavailable */free_pages -= z->free_area[o].nr_free << o;/* Require fewer higher order pages to be free */min >>= 1;if (free_pages <= min)return false;}return true;
}

对于ALLOC_HARDER来说它把watermark水位减去了1/4,而对于ALLOC_HIGH来说,它把保留水位值再减少了1/2,这两个标记按照不同程度来减少保留内存数量,从而达到了更容易成功申请内存的目的。

如果单独设置,从这里也可以看出ALLOC_HIGH是比ALLOC_HARDER更加激进的内存申请方式。但是一般我们申请时设置的GFP_ATOMIC实际上会同时设置ALLOC_HARDER 和 ALLOC_HIGH 标记。

这篇关于如何理解内存管理中的alloc_flags?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/156978

相关文章

Redis实现RBAC权限管理

《Redis实现RBAC权限管理》本文主要介绍了Redis实现RBAC权限管理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1. 什么是 RBAC?2. 为什么使用 Redis 实现 RBAC?3. 设计 RBAC 数据结构

Redis 内存淘汰策略深度解析(最新推荐)

《Redis内存淘汰策略深度解析(最新推荐)》本文详细探讨了Redis的内存淘汰策略、实现原理、适用场景及最佳实践,介绍了八种内存淘汰策略,包括noeviction、LRU、LFU、TTL、Rand... 目录一、 内存淘汰策略概述二、内存淘汰策略详解2.1 ​noeviction(不淘汰)​2.2 ​LR

Golang基于内存的键值存储缓存库go-cache

《Golang基于内存的键值存储缓存库go-cache》go-cache是一个内存中的key:valuestore/cache库,适用于单机应用程序,本文主要介绍了Golang基于内存的键值存储缓存库... 目录文档安装方法示例1示例2使用注意点优点缺点go-cache 和 Redis 缓存对比1)功能特性

Go使用pprof进行CPU,内存和阻塞情况分析

《Go使用pprof进行CPU,内存和阻塞情况分析》Go语言提供了强大的pprof工具,用于分析CPU、内存、Goroutine阻塞等性能问题,帮助开发者优化程序,提高运行效率,下面我们就来深入了解下... 目录1. pprof 介绍2. 快速上手:启用 pprof3. CPU Profiling:分析 C

mac安装nvm(node.js)多版本管理实践步骤

《mac安装nvm(node.js)多版本管理实践步骤》:本文主要介绍mac安装nvm(node.js)多版本管理的相关资料,NVM是一个用于管理多个Node.js版本的命令行工具,它允许开发者在... 目录NVM功能简介MAC安装实践一、下载nvm二、安装nvm三、安装node.js总结NVM功能简介N

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

深入理解Apache Airflow 调度器(最新推荐)

《深入理解ApacheAirflow调度器(最新推荐)》ApacheAirflow调度器是数据管道管理系统的关键组件,负责编排dag中任务的执行,通过理解调度器的角色和工作方式,正确配置调度器,并... 目录什么是Airflow 调度器?Airflow 调度器工作机制配置Airflow调度器调优及优化建议最

Linux内存泄露的原因排查和解决方案(内存管理方法)

《Linux内存泄露的原因排查和解决方案(内存管理方法)》文章主要介绍了运维团队在Linux处理LB服务内存暴涨、内存报警问题的过程,从发现问题、排查原因到制定解决方案,并从中学习了Linux内存管理... 目录一、问题二、排查过程三、解决方案四、内存管理方法1)linux内存寻址2)Linux分页机制3)

Java循环创建对象内存溢出的解决方法

《Java循环创建对象内存溢出的解决方法》在Java中,如果在循环中不当地创建大量对象而不及时释放内存,很容易导致内存溢出(OutOfMemoryError),所以本文给大家介绍了Java循环创建对象... 目录问题1. 解决方案2. 示例代码2.1 原始版本(可能导致内存溢出)2.2 修改后的版本问题在