内存管理器(四) 伙伴算法及分配器原理实现
2015-10-17 22:35
435 查看
内存管理器(四) 伙伴算法
前言
上两篇一共介绍了边界标识算法,以及使用边界标识算法实现了一个堆内存的分配器,现在我们学习下另一种内存管理的算法,我们的Linux的内存管理就广泛应用了伙伴算法。非话不多说。__START
这个算法是什么?
伙伴算法:
伙伴算法(系统)是操作系统中用到的另一种动态存储管理方法。它和边界标识法类似。在用户提出申请时,分配一块恰当的内存区域给用户;反之,在用户释放内存区域的时候收回。不同的是,在伙伴系统中,所有的内存块大小都是以2的整数次幂大小,当然这里立刻暴出一个隐含的问题,就是内存碎片可能会很多。数据结构(纯算法思想的数据结构,并不实用)
#define m 16 typedef struct WORD_B{ WORD_b *llink; int tag; int kval ; WORD_b *rlink; OtherType other; }WORD_b,head; typedef struct HEADNODE{ int nodesize; WORD_b *first; }FREELIST[m+1];
图解分配过程
下面贴上一个分配器原理实现代码
/************************************************************************* > File Name: buddy.c > Author: > Mail: > Created Time: 2015年10月17日 星期六 19时45分14秒 ************************************************************************/ #include<stdio.h> #include<assert.h> #include<unistd.h> #include<sys/mman.h> #include<string.h> #include<errno.h> #include<fcntl.h> #include<pthread.h> #include<stdlib.h> #define GET_LEFT(index) ((index) * 2 + 1) //向左边,扩大2^(k+1) #define GET_RIGHT(index) ((index) * 2 + 2) //依然是扩大,2^(k+1) #define PARENT(index) (((index) + 1)/2 -1) //寻找父块 #define IS_POWER_OF_2(x) (!((x) & ((x) - 1))) //判断这个数子时不是2的幂次 #define MAX(a,b) ((a) > (b) ? (a):(b)) //大小 typedef struct node{ unsigned size; unsigned list[1]; }node; static unsigned fixsize(unsigned size); struct node * node_new(int size); void node_destory(struct node * self); int node_malloc(struct node *self,int size); void node_free(struct node *self,int offset); void node_free(struct node *self,int offset){ //寻找父块合并大小 unsigned node_size ,index = 0; unsigned left_list,right_list; assert(self && offset >= 0 && offset < self->size); node_size = 1; index = offset + self->size -1; for(;self->list[index];index = PARENT(index)){ node_size *= 2; if(index == 0) return ; } self->list[index] = node_size; while(index){ index = PARENT(index); node_size *= 2; left_list = self->list[GET_LEFT(index)]; right_list = self->list[GET_RIGHT(index)]; if(left_list + right_list == node_size) self->list[index] = node_size; else self->list[index] = MAX(left_list,right_list); } } int node_malloc(struct node *self,int size){ unsigned index = 0; unsigned node_size; unsigned offset = 0; if(self == NULL){ //如果空间表为空就返回NULL return -1; } if(size <= 0) //如果需要的空间非法返回1 size = 1; else if(!IS_POWER_OF_2(size)) size = fixsize(size); if(self->list[index] < size) //如果第一标准空间小于size ,那么没有可以分配的大小返回-1 return -1; for(node_size = self->size;node_size != size;node_size/=2){ //寻找相匹配的大小块头编号 if(self->list[GET_LEFT(index)] >= size) index = GET_LEFT(index); else index = GET_RIGHT(index); } self->list[index] = 0; //设置为空 offset = (index + 1) * node_size -self->size; //计算偏移量地址,得出偏移量 while(index){ index = PARENT(index); self->list[index] = MAX(self->list[GET_LEFT(index)],self->list[GET_RIGHT(index)]); } return offset; } void node_destory(struct node * self){ free(self); } struct node * node_new(int size){ //创建主要的空闲表结构,参数为希望创建的大小的2的次幂 struct node * self; unsigned node_size; int i; if(size < 1 || !IS_POWER_OF_2(size)) return NULL; self = (node *)malloc(2 * size * sizeof(unsigned));//创建主要的空闲表结构,给与一个标准值 self->size = size; node_size = size *2; for(i = 0;i < 2*size-1;++i){ if(IS_POWER_OF_2(i+1)) node_size /= 2; self->list[i] = node_size; } return self; } static unsigned fixsize(unsigned size){ //固定size 的大小 size |= size >> 1; //printf("%d\n",size); size |= size >> 2; //printf("%d\n",size); size |= size >> 4; //printf("%d\n",size); size |= size >> 8; //printf("%d\n",size); size |= size >>16; //printf("%d\n",size); return size+1; } int main(){ node * space; space = node_new(32); int a = node_malloc(space,10); int i = 0; node_free(space,a); for(i = 0;i < 9;i++){ printf("the %d\n",space->list[i]); } }
其实伙伴算法的思想简单,但是拘泥于特定的场合,也同意产生内存碎片,所以综合,边界标识法也好,伙伴算法也好,各有优势吧,就像windos ,linux,mac os ; 谁又能下一个结论证明谁更好呢?
相关文章推荐
- 应用领航:盘点那些年我们一起追过的OS
- 无奇不有!盘点各国自己开发的操作系统
- 动易2006序列号破解算法公布
- IE7降低内存和降低CPU的几个技巧
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 如何高效的使用内存
- DOS下内存的配置
- Lua的内存管理浅析
- XP/win2003下发现1G的内存比512M还慢的解决方法
- 可自定义oem的萝卜家园 Ghost XP 新春装机版 V200801 下载
- 超大数据量存储常用数据库分表分库算法总结
- PowerShell实现动态获取当前脚本运行时消耗的内存
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#实现把dgv里的数据完整的复制到一张内存表的方法
- C#算法之关于大牛生小牛的问题
- SQL语句实现查询SQL Server内存使用状况
- C#实现判断操作系统是否为Win8以上版本