linux buddy内存分配管理器,Linux内存管理: Buddy Allocator System

网上说的对buddy system的简单说明。

Divides memory into partitions to try to satisfy a memory request as suitably as possible

- Splits memory into halves to try to give a best-fit

- Invented in 1963, Harry Markowitz

Effectively reduces external fragmentation with small compaction overhead

buddy allocator system算法

buddy allocator是用于分配大于4KB,也就是一个page以上的内存分配时使用的分配器。

buddy allcator除了分配以page为单位的内存之外,另外的功能就是管理分配page之后剩余的page frame,避免出现太多内存碎片。

buddy allocator在每个zone都会单独进行page的管理。

一般都会有11个list,每个list代表一个由1,2,4,8,…,1024个连续的page组成的group。

每组都会被管理在zone数据结构下面的free_area

struct zone {

struct free_area free_area[MAX_ORDER];

}

//MAX_ORDER表明当前组里边page个数最多是2的多少个阶乘。

//可以在mmzone.h文件里边找到如下定义

//#define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER

//比如CONFIG_FORCE_MAX_ZONEORDER是11的话,最大的组里边有2的11次方个page

struct free_area {

struct list_head free_list[MIGRATE_TYPES];

unsigned long nr_free;

};

5b4be6c9abf4b544fa6e4a6a2cb5585c.png

这里提两个问题

放到free_area里边的内存页是怎么分配来的?

1) 在zone里边找到free block

2) 为了找到合适的block,需要根据order的值,在对应的list里边开始找

3) 如果没有的话,就按order递增方向再寻找。找到的话,分配完把剩余的割开放到对应的list里

__rmqueue( )实现free block寻找。需要传zone和order作为参数。会返回第一个page的地址

通过buddy system从free_area获取合适大小的page个数,使用完之后释放是否还是通过buddy system管理?

在释放的时候,会寻找周围是否有可以合并的buddy。进行合并。放到free list中。

__free_pages_bulk()负责释放一组page并按照buddy system的策略合并page。

参数如下:

1) page: 一组内存当中第一个page的地址

2) zone :

3) order:

通过adb可以看到当前的buddyinfo。

这里可以看到每个部分的Node号(如果不是NUMA的话,一般都是0),zone的名字。

然后从左到右是表示2的0次方到2的10次方page大小内存的块的个数。

比如Normal最后的59,表示Normal里边有59个2^10个page大小的连续的内存。

buddy allocator system函数接口

函数说明

struct page * alloc_pages (gfp_t gfp_mask, unsigned int order);

找到2^order个连续的page大小的内存,返回第一个page的地址。

alloc_page(gfp_mask)

取一个page,返回这个page的地址

unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)

使用alloc_pages来获得2^order个page大小的第一个page的地址。

分配成功的话__get_free_pages会返回2^order个page大小的连续的,注意是连续的物理内存的虚拟地址!!

这个可以看一下__get_free_pages()函数的实现,来反证上面说的page连续的问题。

unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)

{

struct page *page;

page = alloc_pages(gfp_mask, order);//找到了2^order个连续的page大小的内存。返回第一个page。

if (!page)

return 0;

return (unsigned long) page_address(page);

//返回这个page对应的地址。要是2^order个page不连续的话,这种实现肯定是有问题的。

}

__get_free_page(gfp_mask)

和上面__get_free_pages差不多,只是返回一个page的虚拟地址。

gfp_mask

如果设置了__GFP_DMA flag

只在ZONE_DMA区域分配page(ARM系统没有这个~~)

如果没有设置__GFP_HIGHMEM flag

没有设置__GFP_HIGHMEM,则page会在ZONE_NORMAL或者ZONE_DMA申请分配。

如果设置了__GFP_HIGHMEM flag

设置了__GFP_HIGHMEM flag,则paga会在ZONE_NORMAL或者ZONE_DMA或者ZONE_HIGHMEM当中进行分配

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值