如何理解内存管理中的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

相关文章

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.

高效管理你的Linux系统: Debian操作系统常用命令指南

《高效管理你的Linux系统:Debian操作系统常用命令指南》在Debian操作系统中,了解和掌握常用命令对于提高工作效率和系统管理至关重要,本文将详细介绍Debian的常用命令,帮助读者更好地使... Debian是一个流行的linux发行版,它以其稳定性、强大的软件包管理和丰富的社区资源而闻名。在使用

深入理解C语言的void*

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下... 目录一、void* 的类型任意性二、编译器对 void* 的类型检查三、需要显式类型转换占用的字节四、总结一、void* 的

深入理解Redis大key的危害及解决方案

《深入理解Redis大key的危害及解决方案》本文主要介绍了深入理解Redis大key的危害及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、背景二、什么是大key三、大key评价标准四、大key 产生的原因与场景五、大key影响与危

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

关于Java内存访问重排序的研究

《关于Java内存访问重排序的研究》文章主要介绍了重排序现象及其在多线程编程中的影响,包括内存可见性问题和Java内存模型中对重排序的规则... 目录什么是重排序重排序图解重排序实验as-if-serial语义内存访问重排序与内存可见性内存访问重排序与Java内存模型重排序示意表内存屏障内存屏障示意表Int

SpringBoot使用minio进行文件管理的流程步骤

《SpringBoot使用minio进行文件管理的流程步骤》MinIO是一个高性能的对象存储系统,兼容AmazonS3API,该软件设计用于处理非结构化数据,如图片、视频、日志文件以及备份数据等,本文... 目录一、拉取minio镜像二、创建配置文件和上传文件的目录三、启动容器四、浏览器登录 minio五、

如何测试计算机的内存是否存在问题? 判断电脑内存故障的多种方法

《如何测试计算机的内存是否存在问题?判断电脑内存故障的多种方法》内存是电脑中非常重要的组件之一,如果内存出现故障,可能会导致电脑出现各种问题,如蓝屏、死机、程序崩溃等,如何判断内存是否出现故障呢?下... 如果你的电脑是崩溃、冻结还是不稳定,那么它的内存可能有问题。要进行检查,你可以使用Windows 11

IDEA中的Kafka管理神器详解

《IDEA中的Kafka管理神器详解》这款基于IDEA插件实现的Kafka管理工具,能够在本地IDE环境中直接运行,简化了设置流程,为开发者提供了更加紧密集成、高效且直观的Kafka操作体验... 目录免安装:IDEA中的Kafka管理神器!简介安装必要的插件创建 Kafka 连接第一步:创建连接第二步:选