内核源码解读之内存管理(10)percpu_page_set分析(代码片段)

奇妙之二进制 奇妙之二进制     2023-01-09     663

关键词:

文章目录

背景

Linux系统中0阶内存分配需求是最多的, 而且经常存在频繁分配释放的行为,如果每次都去伙伴系统中申请,会经常需要获取zone->lock锁住整个zone区域。随着CPU核心数的增加,伙伴系统锁竞争激烈程度也会越来越大。
为了改善这个问题,linux内核中引入了per_cpu_pageset(下面简称pcp)。优化思路是先从zone一次性拿一些页出来,放到每个cpu自己本地中。释放也先放回到这里,等满了再一起还给zone。

数据结构

struct zone 
...
	struct per_cpu_pages	__percpu *per_cpu_pageset;
...
;

内核使用per_cpu_pageset数据结构记录pcp相关信息,其内嵌在zone数据结构中。

/* Fields and list protected by pagesets local_lock in page_alloc.c */
struct per_cpu_pages 
	spinlock_t lock;	/* Protects lists field */
	int count;		/* number of pages in the list */
	int high;		/* high watermark, emptying needed */
	int batch;		/* chunk size for buddy add/remove */
	short free_factor;	/* batch scaling factor during free */
#ifdef CONFIG_NUMA
	short expire;		/* When 0, remote pagesets are drained */
#endif

	/* Lists of pages, one per migrate type stored on the pcp-lists */
	struct list_head lists[NR_PCP_LISTS];
 ____cacheline_aligned_in_smp;

下面为几个关键成员的含义:
count记录了per_cpu缓存中页帧的总数,
high记录了per_cpu缓存中页帧的上限,如果超过这个值就将释放 batch个页帧到伙伴系统中去,如果per_cpu中没有可分配的页帧就从伙伴系统中分配batch个页帧到缓存中来。
per_cpu缓存中的页帧的page就挂接在链表数组struct list_head lists中。

为防止产生过多内存碎片,内核将页帧分类:可移动页,不可移动。内核还定义了一个枚举类型来表示这些可能的类型。

enum migratetype 
	MIGRATE_UNMOVABLE,
	MIGRATE_MOVABLE,
	MIGRATE_RECLAIMABLE,
	MIGRATE_PCPTYPES,	/* the number of types on the pcp lists */
	MIGRATE_HIGHATOMIC = MIGRATE_PCPTYPES,
#ifdef CONFIG_CMA
	/*
	 * MIGRATE_CMA migration type is designed to mimic the way
	 * ZONE_MOVABLE works.  Only movable pages can be allocated
	 * from MIGRATE_CMA pageblocks and page allocator never
	 * implicitly change migration type of MIGRATE_CMA pageblock.
	 *
	 * The way to use it is to change migratetype of a range of
	 * pageblocks to MIGRATE_CMA which can be done by
	 * __free_pageblock_cma() function.
	 */
	MIGRATE_CMA,
#endif
#ifdef CONFIG_MEMORY_ISOLATION
	MIGRATE_ISOLATE,	/* can't allocate from here */
#endif
	MIGRATE_TYPES
;

pcp页帧的类型只可能是:
MIGRATE_UNMOVABLE,
MIGRATE_MOVABLE,
MIGRATE_RECLAIMABLE,

不同类型和大小的pcp页帧挂在不同链表上,所以上面的lists是个数组。

pcp的初始化流程

在内核启动之初per_cpu机制还没有初始化,用于动态分配per_cpu变量的空间还没有分配,所以定义了一个静态的per_cpu变量boot_pageset,用以暂时管理内存域的per_cpu缓存。

mm/page_alloc.c
 
static DEFINE_PER_CPU(struct per_cpu_pageset, boot_pageset);

初始化内存域的zone->pageset字段:

start_kernel

     ------->setup_arch

              ----------->bootmem_init
              
                ------------->zone_sizes_init
                
                    ----------->free_area_init

                          ------------>free_area_init_node
                          
                             ------------->free_area_init_core
                             
                                ------------->zone_init_internals

                                      -------------->zone_pcp_init

内核解读之内存管理内存管理三级架构之page(代码片段)

...级架构,node->zone->page。本节就来介绍page。页是内核管理内存的基本单位,体系结构不同,支持的页大小也不尽相同,还有些体系结构甚至支持几种不同的页大小。大多数32位体系结构支持4KB的页,而64位... 查看详情

内核解读之内存管理内存管理三级架构之page(代码片段)

...级架构,node->zone->page。本节就来介绍page。页是内核管理内存的基本单位,体系结构不同,支持的页大小也不尽相同,还有些体系结构甚至支持几种不同的页大小。大多数32位体系结构支持4KB的页,而64位... 查看详情

内核解读之内存管理开篇介绍

...目录1、开篇介绍2、基本概念1、开篇介绍内存管理是linux内核比较重要的一个模块,其实也是任何操作系统里的一个核心专题。在实际的开发工作中,经常会遇到和内存牵扯的问题,比如内存泄露啊,内存越界等。如果你的技术... 查看详情

内核解读之内存管理开篇介绍

...目录1、开篇介绍2、基本概念1、开篇介绍内存管理是linux内核比较重要的一个模块,其实也是任何操作系统里的一个核心专题。在实际的开发工作中,经常会遇到和内存牵扯的问题,比如内存泄露啊,内存越界等。如果你的技术... 查看详情

内核解读之内存管理内存管理三级架构之内存结点node(代码片段)

文章目录0、概述1、内存节点node0、概述结合NUMA的架构,Linux抽象出了三级内存管理架构:内存节点node、内存区域zone和物理页框page。在NUMA模型中,每个CPU都有自己的本地内存节点(memorynode),而且还可以... 查看详情

内核解读之内存管理内存模型(代码片段)

文章目录1、基本术语2、FLATMEM(平坦内存模型)3、SPARSEMEM稀疏内存模型1、基本术语在介绍内存模型之前需要了解一些基本的知识。1、什么是pageframe?在linux操作系统中,物理内存被分成一页页的pageframe来管理ÿ... 查看详情

内核解读之内存管理内存管理三级架构之内存结点node(代码片段)

文章目录0、概述1、内存节点node2、NUMA的初始化0、概述结合NUMA的架构,Linux抽象出了三级内存管理架构:内存节点node、内存区域zone和物理页框page。在NUMA模型中,每个CPU都有自己的本地内存节点(memorynode)&#x... 查看详情

内核解读之内存管理内存管理三级架构之内存区域zone(代码片段)

文章目录1、zone类型2、zone结构体3、zone的初始化流程1、zone类型NUMA结构下,每个处理器CPU与一个本地内存直接相连,而不同处理器之前则通过总线进行进一步的连接,因此相对于任何一个CPU访问本地内存的速度比访问远程内存的速度... 查看详情

内核解读之内存管理内存管理三级架构之内存区域zone(代码片段)

文章目录1、zone类型2、zone结构体3、zone的初始化流程1、zone类型NUMA结构下,每个处理器CPU与一个本地内存直接相连,而不同处理器之前则通过总线进行进一步的连接,因此相对于任何一个CPU访问本地内存的速度比访问远程内存的速度... 查看详情

内核解读之内存管理内存模型(代码片段)

文章目录基本的术语CONFIG_FLATMEM(平坦内存模型)稀疏的内存模型基本的术语在介绍内存模型之前需要了解一些基本的知识。1、什么是pageframe?在linux操作系统中,物理内存被分成一页页的pageframe来管理,具体... 查看详情

内核解读之内存管理内存管理三级架构之page(代码片段)

...级架构,node->zone->page。本节就来介绍page。页是内核管理内存的基本单位,体系结构不同,支持的页大小也不尽相同,还有些体系结构甚至支持几种不同的页大小。大多数32位体系结构支持4KB的页,而64位... 查看详情

内核解读之内存管理页分配器伙伴系统介绍(代码片段)

文章目录1分配器的需求2伙伴系统的内存组织2.1zonelist列表结构2.2zone的空闲内存结构2.3内存迁移类型2.4pcp页框1分配器的需求伙伴系统是linux的页框分配器,负责系统物理内存的分配工作。由于几乎所有模... 查看详情

内核解读之内存管理页分配器伙伴系统介绍(代码片段)

文章目录1分配器的需求2伙伴系统的内存组织2.1zonelist列表结构2.2zone的空闲内存结构2.3内存迁移类型2.4pcp页框1分配器的需求伙伴系统是linux的页框分配器,负责系统物理内存的分配工作。由于几乎所有模... 查看详情

内核解读之内存管理(9)第一个mm_struct(代码片段)

每个进程或内核线程都由一个任务描述数据结构(task_struct)来管理,每个task_struct中有个structmm_strcut数据结构指针,用来管理任务的虚拟地址空间。而内核本身作为一个进程,也有对应的mm_struct。mm/init-mm.cinit_mm是全系... 查看详情

内核解读之内存管理cpu体系架构uma和numa

文章目录1.SMP(UMA)体系架构2.NUMA体系架构3.NUMA结构基本概念内存和cpu有着密不可分的联系,学习内存管理,先了解下cpu的架构。1.SMP(UMA)体系架构CPU计算平台体系架构分为SMP体系架构和NUMA体系架构等... 查看详情

内核解读之内存管理cpu体系架构uma和numa

文章目录1.SMP(UMA)体系架构2.NUMA体系架构3.NUMA结构基本概念内存和cpu有着密不可分的联系,学习内存管理,先了解下cpu的架构。1.SMP(UMA)体系架构CPU计算平台体系架构分为SMP体系架构和NUMA体系架构等... 查看详情

内核解读之内存管理内存管理三级架构之内存区域zone(代码片段)

...,一个页框就是一个内存的分配单元,可用于任何事情:存放内核数据,用户数据和缓冲磁盘数据等等。任何种类的数据页都可以存放在任页框中,没有任何限制。但是Linux内核又把各个物理内存节点分成n个不同的管理区域zone,这是为... 查看详情

内核解读之内存管理(12)进程虚拟内存管理vm_area_struct与反向映射(代码片段)

...,也就是说用户进程享有前3GB线性地址空间,而内核独享最后1GB线性地址空间。由于虚拟内存的引入,每个进程都可拥有3GB的虚拟内存,并且用户进程之间的地址空间是互不可见、互不影响的,也就是说即使... 查看详情