伙伴系统分析

本文介绍了伙伴系统在Android4.1、Kernel 3.4.0环境下的内存管理,包括基本概念、初始化、内存分配和释放流程。在内存分配中,详细阐述了快速分配和慢速分配的过程,而内存释放则涉及单页和多页的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

chipset: MSM8X25Q

Codebase: Android4.1

Kernel: 3.4.0

 

基本概念:

         关于伙伴系统算法的原理还是比较好理解的,这里不作复数。直接看下关键数据结构。

struct zone {
~~snip
         struct free_area   free_area[MAX_ORDER];        //每一阶以一个元素保存,平台最大11阶。
~~snip
};
可以看到每个zone都有它自己的free_area,效果如下图:

相关信息可以从/proc/buddyinfo读取到,各个值含义依次为节点号, zone类型,后面的值表示从0阶开始各个阶空闲的页数:

#cat/proc/buddyinfo
Node0, zone   Normal     70    27
     33   148     47     13     7      2
  2     1      1
Node0, zone  HighMem      0     1      1      2     2      0      0     0
  0     0      0

struct free_area {
	/*同样阶数保存到一个链表上 */
	struct list_head	free_list[MIGRATE_TYPES];
	/*当前空闲页块的数目。*/
	unsigned long		nr_free;
};

效果如下图:

MIGRATE_TYPES是作为反碎片的一种机制,专有名叫迁移类型。大概的原理就是将伙伴系统的内存页分为几种类型,有可移动,不可移动,可回收等,同一类型的页放在一个区域,如不可回收的页不能放在可移动类型区域,这样对可以移动区域,伙伴系统就可以回收了。

enum {
	MIGRATE_UNMOVABLE,
	MIGRATE_RECLAIMABLE,
	MIGRATE_MOVABLE,
	MIGRATE_PCPTYPES,	/* the number of types on the pcp lists */
	MIGRATE_RESERVE = MIGRATE_PCPTYPES,
#ifdef CONFIG_CMA
	MIGRATE_CMA,
#endif
	MIGRATE_ISOLATE,	/* can't allocate from here */
	MIGRATE_TYPES
};

MIGRATE_UNMOVABLE:不可移动页,在内存中有固定位置,不能移动。核心内核分配的大部分内存属于此类。

MIGRATE_RECLAIMABLE:可回收页,不能移动,但能删除。Kswapd内核线程会操作次区域。

MIGRATE_MOVABLE:可移动又可回收页,用户空间程序使用此类,通过页表映射实现,如果应用程序虚拟地址空间有变化,只要变化页表就可以了。

MIGRATE_RESERVE: 当系统内存相当少而且比较紧急时,才用到此区域。

MIGRATE_CMA:这个是为了避免预留大块内存实现的,当需要大块内存的时候如audio/camera等,它可以被使用;当小内存申请需要时,它也可以被使用,避免了pmem/ion的弊端,不过似乎要基于DMA。后面打算用一篇文章来分析cma.

MIGRATE_ISOLATE: NUMA系统上使用,我们用UMA,不管它。

当某个迁移类型的内存不足时,会向另外一个迁移类型去要内存。这个跟zone的申请机制很像!下面结构规定了当前迁移类型不够时下一个使用的类型,如MIGRATE_UNMOVABLE的使用顺序是: MIGRATE_RECLAIMABLE  -> MIGRATE_RECLAIMABLE -> MIGRATE_MOVABLE -> MIGRATE_RESERVE.

static int fallbacks[MIGRATE_TYPES][4] = {
	[MIGRATE_UNMOVABLE]   = { MIGRATE_RECLAIMABLE, MIGRATE_MOVABLE,     MIGRATE_RESERVE },
	[MIGRATE_RECLAIMABLE] = { MIGRATE_UNMOVABLE,   MIGRATE_MOVABLE,     MIGRATE_RESERVE },
#ifdef CONFIG_CMA
	[MIGRATE_MOVABLE]     = { MIGRATE_CMA,         MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE, MIGRATE_RESERVE },
	[MIGRATE_CMA]         = { MIGRATE_RESERVE }, /* Never used */
#else
	[MIGRATE_MOVABLE]     = { MIGRATE_RECLAIMABLE, MIGRATE_UNMOVABLE,   MIGRATE_RESERVE },
#endif
	[MIGRATE_RESERVE]     = { MIGRATE_RESERVE }, /* Never used */
	[MIGRATE_ISOLATE]     = { MIGRATE_RESERVE }, /* Never used */
};

迁移类型的信息可以从/proc/pagetypeinfo读到: 

#cat /proc/pagetypeinfo
Page block order: 10
Pages per block:  1024

Free pages count per migrate type at order       0      1      2      3      4
    5      6      7      8      9     10
Node    0, zone   Normal, type    Unmovable      1      1      2      0      1
    0      1      1      1      0      0
Node    0, zone   Normal, type    Reclaimable      8     18      3      0      0
    0      0      0      0      0      0
Node    0, zone   Normal, type      Movable      1      1      0    115     46
   12      5      0      0      0      0
Node    0, zone   Normal, type      Reserve      0      0      0      1      0
    1      1      1      1      1      1
Node    0, zone   Normal, type      Isolate      0      0      0      0      0
    0      0      0      0      0      0
Node    0, zone  HighMem, type    Unmovable      0      0      0      0      0
    0      0      0      0      0      0
Node    0, zone  HighMem, type  Reclaimable      0      0      0      0      0
    0      0      0      0      0      0
Node    0, zone  HighMem, type      Movable      0      1      0      0      0
    0      0      0      0      0      0
Node    0, zone  HighMem, type      Reserve      0      0      1      2      2
    0      0      0      0      0      0
Node    0, zone  HighMem, type      Isolate      0      0      0      0      0
    0      0      0      0      0      0

Number of blocks type     Unmovable  Reclaimable      Movable      Reserve
Isolate
Node 0, zone   Normal           13            8          178            2
     0
Node 0, zone  HighMem            1            0           14            1
     0

初始化:

首先对伙伴系统相关数据结构初始化,有如下调用流程:

start_kernel -> setup_arch ->paging_init -> bootmem_init -> arm_bootmem_free ->

free_area_init_node ->init_currently_empty_zone -> zone_init_free_lists

static void __meminit zone_init_free_lists(struct zone *zone)
{
	int order, t;
	/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值