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

相关文章

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

python uv包管理小结

《pythonuv包管理小结》uv是一个高性能的Python包管理工具,它不仅能够高效地处理包管理和依赖解析,还提供了对Python版本管理的支持,本文主要介绍了pythonuv包管理小结,具有一... 目录安装 uv使用 uv 管理 python 版本安装指定版本的 Python查看已安装的 Python

深入理解Apache Kafka(分布式流处理平台)

《深入理解ApacheKafka(分布式流处理平台)》ApacheKafka作为现代分布式系统中的核心中间件,为构建高吞吐量、低延迟的数据管道提供了强大支持,本文将深入探讨Kafka的核心概念、架构... 目录引言一、Apache Kafka概述1.1 什么是Kafka?1.2 Kafka的核心概念二、Ka

基于Python和MoviePy实现照片管理和视频合成工具

《基于Python和MoviePy实现照片管理和视频合成工具》在这篇博客中,我们将详细剖析一个基于Python的图形界面应用程序,该程序使用wxPython构建用户界面,并结合MoviePy、Pill... 目录引言项目概述代码结构分析1. 导入和依赖2. 主类:PhotoManager初始化方法:__in

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

nvm如何切换与管理node版本

《nvm如何切换与管理node版本》:本文主要介绍nvm如何切换与管理node版本问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录nvm切换与管理node版本nvm安装nvm常用命令总结nvm切换与管理node版本nvm适用于多项目同时开发,然后项目适配no

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