伙伴分配器

Linux内存管理-伙伴分配器 linux内核伙伴系统分配内存源码分析 阅读详情

伙伴分配器定义

基本的伙伴分配器

连续的物理页合在一起称为页块(page block); 阶(order)是伙伴分配器中的一个专业术语,是页的数量单位,2^n个连续的物理页成为n阶页块;
满足以下条件的两个n阶页块称为伙伴(buddy):
1、两个页块是相邻的,即物理地址是连续的;
2、页块的第一页的物理页号必须是2^n的整数倍;
3、如果合并成(n+1)阶页块,第一页的物理页号必须是2^(n+1)的整数倍。
这是伙伴分配器(buddy allocator)的名字的来源;
以单页(0阶页块)为例,0号页和1号页是伙伴,2号页和3号页是伙伴;1号页和2号页不是伙伴,因为1号页和2号页合并成1阶页块,第一个页即1号页不是2^(0+1)的整数倍;

伙伴分配器分配和释放物理页的数量单位为阶。分配n阶页块的过程如下:
1、查看是否有空闲的n阶页块,如果有直接分配;否则,继续执行下一步;
2、查看是否存在空闲的(n+1)阶页块,如果有,把(n+1)阶页块分裂为两个n阶
页块,一个插入空闲n阶页块链表,另一个分配出去;否则继续执行下一步。
3、查看是否存在空闲的(n+2)阶页块,如果有把(n+2)阶页块分裂为两个(n+1)
阶页块,一个插入空闲(n+1)阶页块链表,另一个分裂为两个n阶页块,一个插入空闲n阶页
块链表,另一个分配出去;如果没有,继续查看更高阶是否存在空闲页块。

释放n阶页块时,查看它的伙伴是否空闲;如果伙伴不空闲,则把n阶页块插入空闲的n阶页块链表;如果伙伴空闲,则合并为(n+1)阶页块,接下来释放(n+1)阶页块;

内核在基本的分区伙伴分配器的基础上做了一些扩展:

  1. 对于内存的管理是基于节点(node,即pglist_data)和区域(zone)的,成为分区的伙伴分配器(zoned buddy allocator);
  2. 为了预防内存碎片,把物理页根据可移动性分组;
  3. 针对分配单页做了性能优化,为了减少处理器之间的锁竞争,在内存区域(zone)中增加一个每处理器页集合;

对于可移动性分组和每处理器页集合,本文不做介绍,可以查阅相关资料进行了解;

分区伙伴分配器

数据结构

分区的伙伴分配器基于某个内存节点(node)的某个区域(zone);struct zone中的成员free_area维护空闲页块,数组下标对那个页块的阶数(order);struct free_area中的成员free_list表示空闲页块的链表;free_list本身是一个数组,数组的成员是链表;free_list数组的下标对应可移动性类型(migrate
type),空闲页块根据migrate type分组;
struct zone中的成员managed_pages是伙伴分配器管理的物理页的数量;

struct zone {
    /* Read-mostly fields */

    /* zone watermarks, access with *_wmark_pages(zone) macros */
    unsigned long watermark[NR_WMARK];


    long lowmem_reserve[MAX_NR_ZONES];

    #ifdef CONFIG_NUMA
    int node;
    #endif
    struct pglist_data	*zone_pgdat;
    struct per_cpu_pageset __percpu *pageset;

    #ifndef CONFIG_SPARSEMEM
    /*
    * Flags for a pageblock_nr_pages block. See pageblock-flags.h.
      * In SPARSEMEM, this map is stored in struct mem_section
      */
    unsigned long		*pageblock_flags;
    #endif /* CONFIG_SPARSEMEM */

    /* zone_start_pfn == zone_start_paddr >> PAGE_SHIFT */
    unsigned long		zone_start_pfn;

    unsigned long		managed_pages;
    unsigned long		spanned_pages;
    unsigned long		present_pages;

        /* free areas of different sizes */
        struct free_area	free_area[MAX_ORDER];

} ____cacheline_internodealigned_in_smp;

struct free_area {
	struct list_head	free_list[MIGRATE_TYPES];
	unsigned long		nr_free;
};

MAX_ORDER是最大阶数,伙伴分配器可分配的最大阶数是(MAX_ORDER - 1);

/* Free memory management - zoned buddy allocator.  */
#ifndef CONFIG_FORCE_MAX_ZONEORDER
#define MAX_ORDER 11
#else
#define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER
#endif
#define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1))

内存区域时如何连接的?内存区域中第一页内的链表元素,可用于将内存区域维持在链表中;
image.png

首选区域(zone),备用区域(zonelist)

每个内存节点的struct pglist_data中,有两个成员node_zones、node_zonelists;node_zones表示该node中的内存区域数组,node_zonelists表示备用区域数组;

typedef struct pglist_data {
	struct zone node_zones[MAX_NR_ZONES]; // 内存区域数组
	struct zonelist node_zonelists[MAX_ZONELISTS]; // 备用区域数组
	int nr_zones;
    ...
} pg_data_t;

/*
 * One allocation request operates on a zonelist. A zonelist
 * is a list of zones, the first one is the 'goal' of the
 * allocation, the other zones are fallback zones, in decreasing
 * priority.
 *
 * To speed the reading of the zonelist, the zonerefs contain the zone index
 * of the entry being read. Helper functions to access information given
 * a struct zoneref are
 *
 * zonelist_zone()	- Return the struct zone * for an entry in _zonerefs
 * zonelist_zone_idx()	- Return the index of the zone for an entry
 * zonelist_node_idx()	- Return the index of the node for an entry
 */
struct zonelist {
	struct zoneref _zonerefs[MAX_ZONES_PER_ZONELIST + 1];
};

分配内存页块时,首先会尝试从首选内存区域分配,在首选的内存区域无法满足内存分配请求时,首先尝试同一节点的另一个内存区域,接下来再尝试另一个节点,直至满足请求;后面的内存区域叫做备用区域;
所有内存区域和节点的伙伴系统都通过备用区域列表连接起来;
image.png

如果首选的内存区域不能满足页分配请求,可以从备用的内存区域借用物理页;借用的规则涉及到区域类型;

enum zone_type {
#ifdef CONFIG_ZONE_DMA
	ZONE_DMA,
#endif
#ifdef CONFIG_ZONE_DMA32
	ZONE_DMA32,
#endif
	ZONE_NORMAL,
#ifdef CONFIG_HIGHMEM
	ZONE_HIGHMEM,
#endif
	ZONE_MOVABLE,
#ifdef CONFIG_ZONE_DEVICE
	ZONE_DEVICE,
#endif
	__MAX_NR_ZONES

};

内存区域借用的规则如下:

  1. 一个内存节点的某个区域类型可以从另一个内存节点的相同区域类型借用物理页;例如节点0的普通区域可以从节点1的普通区域借用物理页;
  2. 高区域类型可以从低区域类型借用物理页,例如普通区域可以从DMA区域借用物理页;
  3. 低区域类型不能从高区域类型借用物理页,例如DMA区域不能从普通区域借用物理页;
根据分配标志得到首选区域类型

申请页时,最低的4个标志位用来指定首选的内存区域类型;通过函数gfp_zone确定首选内存区域类型;

#define ___GFP_DMA		0x01u
#define ___GFP_HIGHMEM		0x02u
#define ___GFP_DMA32		0x04u
#define ___GFP_MOVABLE		0x08u


#define GFP_ZONE_TABLE ( \
	(ZONE_NORMAL << 0 * GFP_ZONES_SHIFT)				       \
	| (OPT_ZONE_DMA << ___GFP_DMA * GFP_ZONES_SHIFT)		       \
	| (OPT_ZONE_HIGHMEM << ___GFP_HIGHMEM * GFP_ZONES_SHIFT)	       \
	| (OPT_ZONE_DMA32 << ___GFP_DMA32 * GFP_ZONES_SHIFT)		       \
	| (ZONE_NORMAL << ___GFP_MOVABLE * GFP_ZONES_SHIFT)		       \
	| (OPT_ZONE_DMA << (___GFP_MOVABLE | ___GFP_DMA) * GFP_ZONES_SHIFT)    \
	| (ZONE_MOVABLE << (___GFP_MOVABLE | ___GFP_HIGHMEM) * GFP_ZONES_SHIFT)\
	| (OPT_ZONE_DMA32 << (___GFP_MOVABLE | ___GFP_DMA32) * GFP_ZONES_SHIFT)\
)

static inline enum zone_type gfp_zone(gfp_t flags)
{
	enum zone_type z;
	int bit = (__force int) (flags & GFP_ZONEMASK);

	z = (GFP_ZONE_TABLE >> (bit * GFP_ZONES_SHIFT)) &
					 ((1 << GFP_ZONES_SHIFT) - 1);
	VM_BUG_ON((GFP_ZONE_BAD >> bit) & 1);
	return z;
}
区域水线

首选的内存区域什么情况下需要从备用区域借用物理页呢?即首选内存区域不能满足页分配的请求;这个问题涉及到区域水线;
每个内存区域有3个水线:

  1. 高水线(high):如果内存区域的空闲页数大于高水线,说明该内存区域的内存充足;
  2. 低水线(low):如果内存区域的空闲页数小于低水线,说明该内存区域的内存轻微不足;
  3. 最低水线(min):如果内存区域的空闲页数小于最低水线,说明该内存区域的内存严重不足;

enum zone_watermarks {
	WMARK_MIN,
	WMARK_LOW,
	WMARK_HIGH,
	NR_WMARK
};

#define min_wmark_pages(z) (z->watermark[WMARK_MIN])
#define low_wmark_pages(z) (z->watermark[WMARK_LOW])
#define high_wmark_pages(z) (z->watermark[WMARK_HIGH])

struct zone {
	/* Read-mostly fields */

	/* zone watermarks, access with *_wmark_pages(zone) macros */
	unsigned long watermark[NR_WMARK];

    ...
	/*
	 * spanned_pages is the total pages spanned by the zone, including
	 * holes, which is calculated as:
	 * 	spanned_pages = zone_end_pfn - zone_start_pfn;
	 *
	 * present_pages is physical pages existing within the zone, which
	 * is calculated as:
	 *	present_pages = spanned_pages - absent_pages(pages in holes);
	 *
	 * managed_pages is present pages managed by the buddy system, which
	 * is calculated as (reserved_pages includes pages allocated by the
	 * bootmem allocator):
	 *	managed_pages = present_pages - reserved_pages;
	 */
    unsigned long		managed_pages;
    unsigned long		spanned_pages;
    unsigned long		present_pages;

	...
};

struct zone中的watermark数组,表示high,low,min三个水线;min水线以下的内存称为紧急保留内存;
申请页时,第一次尝试使用低水线,如果首选内存区域的空闲页数小于低水线,就从备用内存区域借用物理页;如果第一次分配失败,那么唤醒所有目标内存节点的页回收内核线程hswapd以异步回收页,然后尝试使用最低水线;如果首选内存区域的空闲页数小于最低水线,就从备用内存区域借用物理页;

内存区域的水线可以查询:

Node 0, zone      DMA
  pages free     3721
        min      33
        low      41
        high     49
        spanned  4095
        present  3743
        managed  3721

Node 0, zone   Normal
  pages free     819743
        min      7968
        low      9960
        high     11952
        spanned  919040
        present  919040
        managed  884306
    
Node 0, zone   Normal
  pages free     819743
        min      7968
        low      9960
        high     11952
        spanned  919040
        present  919040
        managed  884306

spanned,present,managed含义如下:

spanned_pages = zone_end_pfn - zone_start_pfn; //区域结束的物理页减去起始页=当前区域跨越的总页数(包括空洞) 
present_pages = spanned_pages - absent_pages(pages in holes) //当前区域跨越的总页数-空洞页数=当前区域可用物理页数 
managed_pages = present_pages - reserved_pages //当前区域可用物理页数-预留的页数=伙伴分配器管理物理页数

备用区域列表

内存节点的pg_data_t中定义了备用区域列表;

typedef struct pglist_data {
	struct zone node_zones[MAX_NR_ZONES]; // 内存区域数组
	struct zonelist node_zonelists[MAX_ZONELISTS]; // 备用区域数组
	int nr_zones;
    ...
} pg_data_t;

enum {
	ZONELIST_FALLBACK,	/* zonelist with fallback */
#ifdef CONFIG_NUMA
	/*
	 * The NUMA zonelists are doubled because we need zonelists that
	 * restrict the allocations to a single node for __GFP_THISNODE.
	 */
	ZONELIST_NOFALLBACK,	/* zonelist without fallback (__GFP_THISNODE) */
#endif
	MAX_ZONELISTS
};

/* Maximum number of zones on a zonelist */
#define MAX_ZONES_PER_ZONELIST (MAX_NUMNODES * MAX_NR_ZONES)
struct zonelist {
	struct zoneref _zonerefs[MAX_ZONES_PER_ZONELIST + 1];
};

/*
 * This struct contains information about a zone in a zonelist. It is stored
 * here to avoid dereferences into large structures and lookups of tables
 */
struct zoneref {
	struct zone *zone;	/* Pointer to actual zone */
	int zone_idx;		/* zone_idx(zoneref->zone) */
};

UMA系统只有一个备用区域列表,按区域类型从高到低排序;假设UMA系统包含普通区域和DMA区域,那么备用区域列表是:{普通区域,DMA区域};
NUMA系统的每个内存节点有两个备用区域列表:一个包含所有内存节点的区域,另一个只包含当前内存节点的区域;如果申请页时指定flag中包含__GFP_THISNODE,从当前内存节点分配物理页,就需要从第二个备用区域列表中分配;

包含所有内存节点的备用区域列表有两种排序方法:

  1. 节点优先顺序:先根据节点距离从小到大排序,然后在每个节点里面根据区域类型从高到低排序;
  2. 区域优先顺序:先根据区域类型从高到低排序,然后再每个区域类型里面根据节点距离从小到大排序;

节点优先顺序有点是优先选择距离近的内存,缺点是在高区域耗尽以前就使用低区域;例如DMA区域一般比较小,节点优先顺序会增大DMA区域耗尽的概率;
区域优先顺序的有点是减小区域耗尽的概率,缺点是不能保证优先选择距离近的内存;
可以使用内核参数"numa_zonelist_order"指定排序方法;

Node

可移动性分组

后续调查补充

每处理器页集合

后续调查补充

核心函数的实现

在Linux内核中,所有分配页的函数最终都会调用到__alloc_pages_nodemask,此函数被称为分区的伙伴分配器的心脏。

/*
 * This is the 'heart' of the zoned buddy allocator.
 */
struct page *
__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
			struct zonelist *zonelist, nodemask_t *nodemask)
{
	struct page *page;
	unsigned int alloc_flags = ALLOC_WMARK_LOW;
	gfp_t alloc_mask = gfp_mask; /* The gfp_t that was actually used for allocation */
	struct alloc_context ac = { };

	gfp_mask &= gfp_allowed_mask;
	if (!prepare_alloc_pages(gfp_mask, order, zonelist, nodemask, &ac, &alloc_mask, &alloc_flags))
		return NULL;

	finalise_ac(gfp_mask, order, &ac);

	/* First allocation attempt */
	page = get_page_from_freelist(alloc_mask, order, alloc_flags, &ac);
	if (likely(page))
		goto out;

	/*
	 * Apply scoped allocation constraints. This is mainly about GFP_NOFS
	 * resp. GFP_NOIO which has to be inherited for all allocation requests
	 * from a particular context which has been marked by
	 * memalloc_no{fs,io}_{save,restore}.
	 */
	alloc_mask = current_gfp_context(gfp_mask);
	ac.spread_dirty_pages = false;

	/*
	 * Restore the original nodemask if it was potentially replaced with
	 * &cpuset_current_mems_allowed to optimize the fast-path attempt.
	 */
	if (unlikely(ac.nodemask != nodemask))
		ac.nodemask = nodemask;

	page = __alloc_pages_slowpath(alloc_mask, order, &ac);

out:
	if (memcg_kmem_enabled() && (gfp_mask & __GFP_ACCOUNT) && page &&
	    unlikely(memcg_kmem_charge(page, gfp_mask, order) != 0)) {
		__free_pages(page, order);
		page = NULL;
	}

	if (kmemcheck_enabled && page)
		kmemcheck_pagealloc_alloc(page, order, gfp_mask);

	trace_mm_page_alloc(page, order, alloc_mask, ac.migratetype);

	return page;
}
EXPORT_SYMBOL(__alloc_pages_nodemask);

__alloc_pages_nodemask函数的算法流程:
1、根据分配标志位得到首选区域类型和迁移类型;
2、执行快速路径,使用低水线尝试第一次分配;
3、如果快速路径分配失败,执行慢速路径。

参考文献

  1. 《linux内核深度解析》,余华兵著
  2. 《professional linux kernel architecture》,Wolfgang Mauerer 著,郭旭 译
buddy_allocator:伙伴系统内存分配器 buddy_allocator buddy system memory allocator from Linux kernel System Storage 两个大小相等且邻接的内存块被称作伙伴。 如果两个伙伴都是空闲的,会将其合并成一个更大的内存块,作为下一层次上某个内存块的伙伴。 page分为两类: 属于Buddy系统(PG_buddy,待分配) page->order记录order(page所属的free_area也表示了其order),用于合并时的检测 不属于Buddy系统(已分配) 单页:page->order记录order 组合页:首个(PG_head)page记录order,其余(PG_tail)指向首页。order用于释放时的解组合 =============== Buddy Allocator 每次把一个大的内存块对半切分,一直切到需要的大小。 ============= 立即下载

相关推荐

NOIP2008年普及组初赛题目答案及解析

NOIP2008年初赛详细题解

城南蝈蝈 926

内存学习(七):伙伴分配器(正式版)1

当前使用的页分配器是伙伴分配器,伙伴分配器的特点是算法简单且效率高。(接力棒由之前memblock交给了伙伴分配器)

叫好与叫座虽然不是对立面,但想在同一个作品中达到双重效果很难。 519

基于文件通信的QMT量化交易信号桥接方案设计与实现

在量化交易系统开发中,进程间通信(IPC)是连接不同计算模块、实现策略逻辑与交易执行解耦的关键技术。其核心原理在于允许运行于独立环境或进程的程序安全、可靠地交换数据。文件系统通信作为一种经典的IPC方法,因其实现简单、跨平台兼容性好且数据可持久化,在非高频场景下具有重要技术价值。它尤其适用于需要将外部复杂计算环境(如配备丰富数据科学库的Python环境)与专用交易终端(如迅投QMT)集成的应用场景。通过约定文件路径与数据格式,外部程序可将包含交易指令的JSON信号文件写入特定目录,而交易终端通过轮询或监听机

weixin_28678151的博客 419

内存管理专题04 伙伴分配器原理

伙伴分配器

weixin_42154057的博客 916

【Python】torch_npu

Ascend AI处理器核心计算范式与PyTorch的桥接艺术:深入探索torch_npu的基石要真正理解,我们必须首先超越其作为PyTorch后端库的表面认知,深入其所服务的硬件——华为昇腾(Ascend)AI处理器的核心计算范式。这不仅仅是关于如何在NPU上运行PyTorch模型,更是关于NPU如何设计其计算,以及如何巧妙地将这种硬件特性映射到PyTorch的抽象层之上。1. 昇腾AI处理器的达芬奇架构:极致算力的源泉昇腾AI处理器并非传统的CPU或GPU。它采用了华为独创的达芬奇(Da Vinci)架

宅男很神经 5372

强化学习入门8—深入理解DDPG

本文是强化学习入门系列的第八篇,前面我们讲Actor-Critic时提到了DDPG。DDPG是google DeepMind团队提出的一种用于输出确定性动作的算法,它解决了Actor-Critic 神经网络每次参数更新前后都存在相关性,导致神经网络只能片面的看待问题这一缺点。同时也解决了DQN不能用于连续性动作的缺点。

小菜羊的博客 4315

Linux 内核内存管理一(物理内存管理)

linux 物理内存管理

weixin_39077305的博客 1288

Vue3 + OpenLayers 开发指南(一) - 环境搭建与基础配置

本文详细介绍了如何从零开始搭建Vue3与OpenLayers的集成开发环境。通过项目初始化、核心依赖安装、目录结构规划及基础配置,手把手引导开发者创建一个结构清晰、可维护的现代化WebGIS应用骨架,为后续添加地图图层和交互功能奠定坚实基础。

weixin_28049429的博客 340

【Linux 内核 内存管理】分区伙伴分配器 ① ( 分区伙伴分配器源码数据结构 | free_area 空闲区域数组 | MAX_ORDER 宏定义 | 空闲区域的页最大阶数 )

一、分区伙伴分配器、 二、分区伙伴分配器源码数据结构、 1、free_area 空闲区域数组、 2、MAX_ORDER 宏定义 ( 空闲区域的页最大阶数 )

让 学习 成为一种 习惯 ( 韩曙亮 の 技术博客 ) 2429

面向企业架构师的 SAP BTP 全景实践:多云、账户、运行时与端到端开发路径

摘要:SAP BTP为企业提供多云、多运行时(Cloud Foundry/Kyma/ABAP Cloud)的数字化转型平台,支持快速构建扩展应用。关键选择包括:1)根据合规与性能选择区域;2)区分Trial(90天限制)与Free Tier(无期限)方案;3)按场景选择运行时(CF适合微服务/Kyma适合云原生/ABAP Cloud适合S/4HANA扩展)。建议优先使用Free Tier进行POC,并通过BTP Cockpit统一管理,实现从验证到生产的平滑过渡。(150字)

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 253

Yocto开发讲解系列 - 总目录

Yocto开发讲解系列总纲Yocto开发专栏前言

fulinux的博客 3万+

Linux内核伙伴分配器

当系统内核初始化完毕后,使用页分配器管理物理页,当使用的页分配器是伙伴分配器,伙伴分配器的特点是算法简单且高效。连续的物理页称为页块(page block)。阶(order)是伙伴分配器的专业术语,是页的数量单位,2的n次方个连续页称为n阶页块。满足以下条件的两个n阶页块称为伙伴(buddy --> 英 [ˈbʌdi]):1.两个页块相邻,物理地址连续;2.页块第一页的物理页号是2n的整数倍;3.若合并成(n+1)阶页块,第一页的物理页号需是2n+1的整数倍。

m0_74186706的博客 1609

【保姆级教程】YOLOv8_Pose多目标+关键点检测:训练自己的数据集

【保姆级教程】YOLOv8_Pose多目标+关键点检测:训练自己的数据集

m0_51579041的博客 1万+

伙伴分配器(buddy allocator)和slab

文章目录伙伴分配器(buddy allocator)和slaba.原理b. 数据结构slab 分配器用户API数据结构 伙伴分配器(buddy allocator)和slab 当系统内核初始化完毕后,使用页分配器管理物理页,当使用的页分配器是伙伴分配器,伙伴分配器的特点是算法简单且高效。连续的物理页称为页块(page block)。阶(order)是伙伴分配器的一个专业术语,是页的数量单位,2n2^n2n个连续页称为n阶页块。物理内存被分成多个order:0 ~ 10,每个order中连续page的个数是2

Birate的博客 2872

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

【Linux 内核 内存管理】伙伴分配器 ① ( 伙伴分配器引入 | 页块、阶 | 伙伴 )

一、伙伴分配器引入、 二、页块、阶、 三、伙伴

让 学习 成为一种 习惯 ( 韩曙亮 の 技术博客 ) 1919

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

【Linux】伙伴系统和slab分配器

Linux内核的)是物理内存管理的核心机制,负责管理物理页框的分配与释放。伙伴系统的核心目标是:高效管理连续物理内存,减少外部碎片,同时通过合并空闲块快速响应大块内存请求。伙伴系统是linux内存管理的底层基础,slab等上层分配器依赖它获取大块内存后进一步细分。

目标:MVP 645

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

小学一下伙伴分配器

关于内管管理这个部分,我一直是很疑惑的。有时候学习起来。也不具有连贯性,当然这个很大的可能性的原因,是因为没有和之前的学习联系起来。不过对于我这样的笨崽崽,重复也是一种不值得提倡但是有效的学习方法之一哦。后面接着学习一下前辈的buddy\slab等几个内存分配机制。

叫好与叫座虽然不是对立面,但想在同一个作品中达到双重效果很难。 262

Linux 内存管理(1):伙伴分配器与 SLAB 分配器深度解析

1. 地址计算规则伙伴块地址计算公式:伙伴地址 = 块地址 ^ (1 << (order + PAGE_SHIFT))示例:Order 1 块(2 页)在 0x1000:0x1000 ^ (1 << (1+12)) = 0x1000 ^ 0x2000 = 0x30002. 内部碎片问题请求大小实际分配碎片率1 页1 页0%3 页4 页25%5 页8 页37.5%7 页8 页12.5%

小嵌同学的博客 1546

伙伴分配器的内核实现

内核中的伙伴分配器

qq_53111905的博客 869

内存管理(十):伙伴分配器

1、伙伴分配器概述 内核初始化完毕后,使用页分配管理器管理物理页,当前使用的页分配器是伙伴分配器。 页分配管理自然而然,分配的单位是页。并且伙伴分配器只能分配2的n次幂个页,n称为阶(order),2的n次幂个连续页称为n阶页块。满足以下条件的两个n阶页块称为伙伴(buddy) 两个页块的物理地址是连续的 页块的第一页的物理页号必须是2的n次幂的整数倍,如0号页,2号页,4号页,8号页… 如果合并成(n+1)阶页块,第一页的物理页号必须是2的(n+1)次幂的整数倍。如两个2阶页块合并,第一页应是0,4,8

进步源于记录,优秀来自分享 955

伙伴系统与slab/slub分配器

    内存管理有两个算法:伙伴算法和slab/slub算法。伙伴算法是以页为单位管理内存,slab算法是以字节为单位管理内存,是内核的小内存管理算法。slab分配器并没有脱离伙伴系统,而是基于伙伴系统分配的大内存进一步细分成小内存。先讲伙伴系统,再讲slab分配器。      伙伴系统是基于bootmem机制来分配一些数据结构的。bootmem初始化的时候会调用free_area_init_n...

Joe的专栏 1443

【Linux 内核源码分析】内存管理——伙伴分配器

在Linux操作系统中,内存分配通常由内核中的内存管理模块完成。:这是内核中最基本的分配器,用于分配物理内存。伙伴系统将内存块组织成不同大小的伙伴,以便有效地分配和回收内存。它适用于分配较大的内存块。:slab分配器是一个对象缓存,用于高效地分配和回收小块内存。它将内存组织成缓存,每个缓存包含相同大小的对象。slab分配器特别适合为内核对象分配内存,如进程描述符、文件描述符等。:vmalloc是一个用于虚拟内存分配的分配器。它主要用于分配大块内存,并且不要求物理连续性,而是提供虚拟连续的内存区域。

C/C++Linux、音视频、DPDK 1796

linux内存管理系列——伙伴分配器

linux内存管理——伙伴分配器学习笔记

qq_41952309的博客 800

【Linux】【内存管理】伙伴系统和slab分配器

Linux内核采用伙伴系统与slab分配器两级机制管理物理内存。伙伴系统以页为单位管理大块连续内存,通过分割合并策略减少外部碎片,适合分配大块内存。slab分配器在此基础上细分小对象,通过预分配、对象复用和缓存优化提升小内存分配效率。两者协同工作,伙伴系统提供底层页框支持,slab构建对象缓存层,共同实现高效内存管理。伙伴系统优势在于大块连续内存管理,而slab擅长高频小对象分配,但都存在一定内存开销和复杂度问题。这种层级设计平衡了内存利用率与分配性能的需求。

张壮壮的博客 1288

Linux 内核中的内存分配器:从伙伴系统到 Slab

Linux 内核中的内存分配器是一个核心组件,它负责分配和管理系统的内存资源。内存分配器通过伙伴系统、Slab 分配器、Slub 分配器等机制,实现了内存的高效分配和管理。工作也要流程化,内存分配器就像是系统中的资源分配工具,它确保了内存资源的合理分配和使用。在实际应用中,我们需要选择合适的分配函数,合理设置分配标志,使用 Slab 分配器,及时释放内存,以及监控内存使用情况,以实现系统的最佳性能和可靠性。

jiang_style的博客 4535

linux内存管理(六)-伙伴分配器

linux内存三大分配器:引导内存分配器,伙伴分配器,slab分配器 二、伙伴分配器 1.伙伴分配器原理 物理内存被分成11个order:0 ~ 10,每个order中连续page的个数是2order,如果一个order中可用的memory size小于期望分配的size,那么更大order的内存块会被对半切分,切分之后的两个小块互为buddies。其中一个子块用于分配,另一个空闲的。这些块在必要时会连续减半,直到达到所需大小的memory 块为止,当一个block被释放之后,会检查它的buddies是否也

jianjian的博客 2057
上一篇: netlink原理及应用
下一篇: slab分配器
congchp
博客等级 码龄9年 354粉丝 99原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值