Buddy Memorry

  1 #include "buddy.h"
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <stdint.h>
  5 #include <assert.h>
  6 #include <string.h>
  7
  8 #define NODE_UNUSED 0
  9 #define NODE_USED 1
 10 #define NODE_SPLIT 2
 11 #define NODE_FULL 3
 12
 13 struct buddy {
 14     int level;
 15     uint8_t tree[1];
 16 };
 17
 18 struct buddy *
 19 buddy_new(int level) {
 20     int size = 1 << level;
 21     struct buddy * self = malloc(sizeof(struct buddy) + sizeof(uint8_t) * (size * 2 - 2));
 22     self->level = level;
 23     memset(self->tree , NODE_UNUSED , size*2-1);
 24     return self;
 25 }
 26
 27 void
 28 buddy_delete(struct buddy * self) {
 29     free(self);
 30 }
 31
 32 static inline int
 33 is_pow_of_2(uint32_t x) {
 34     return !(x & (x-1));
 35 }
 36
 37 static inline uint32_t
 38 next_pow_of_2(uint32_t x) {
 39     if ( is_pow_of_2(x) )
 40         return x;
 41     x |= x>>1;
 42     x |= x>>2;
 43     x |= x>>4;
 44     x |= x>>8;
 45     x |= x>>16;
 46     return x+1;
 47 }
 48
 49 static inline int
 50 _index_offset(int index, int level, int max_level) {
 51     return ((index + 1) - (1 << level)) << (max_level - level);
 52 }
 53
 54 static void
 55 _mark_parent(struct buddy * self, int index) {
 56     for (;;) {
 57         int buddy = index - 1 + (index & 1) * 2;
 58         if (buddy > 0 && (self->tree[buddy] == NODE_USED ||    self->tree[buddy] == NODE_FULL)) {
 59             index = (index + 1) / 2 - 1;
 60             self->tree[index] = NODE_FULL;
 61         } else {
 62             return;
 63         }
 64     }
 65 }
 66
 67 int
 68 buddy_alloc(struct buddy * self , int s) {
 69     int size;
 70     if (s==0) {
 71         size = 1;
 72     } else {
 73         size = (int)next_pow_of_2(s);
 74     }
 75     int length = 1 << self->level;
 76
 77     if (size > length)
 78         return -1;
 79
 80     int index = 0;
 81     int level = 0;
 82
 83     while (index >= 0) {
 84         if (size == length) {
 85             if (self->tree[index] == NODE_UNUSED) {
 86                 self->tree[index] = NODE_USED;
 87                 _mark_parent(self, index);
 88                 return _index_offset(index, level, self->level);
 89             }
 90         } else {
 91             // size < length
 92             switch (self->tree[index]) {
 93             case NODE_USED:
 94             case NODE_FULL:
 95                 break;
 96             case NODE_UNUSED:
 97                 // split first
 98                 self->tree[index] = NODE_SPLIT;
 99                 self->tree[index*2+1] = NODE_UNUSED;
100                 self->tree[index*2+2] = NODE_UNUSED;
101             default:
102                 index = index * 2 + 1;
103                 length /= 2;
104                 level++;
105                 continue;
106             }
107         }
108         if (index & 1) {
109             ++index;
110             continue;
111         }
112         for (;;) {
113             level--;
114             length *= 2;
115             index = (index+1)/2 -1;
116             if (index < 0)
117                 return -1;
118             if (index & 1) {
119                 ++index;
120                 break;
121             }
122         }
123     }
124
125     return -1;
126 }
127
128 static void
129 _combine(struct buddy * self, int index) {
130     for (;;) {
131         int buddy = index - 1 + (index & 1) * 2;
132         if (buddy < 0 || self->tree[buddy] != NODE_UNUSED) {
133             self->tree[index] = NODE_UNUSED;
134             while (((index = (index + 1) / 2 - 1) >= 0) &&  self->tree[index] == NODE_FULL){
135                 self->tree[index] = NODE_SPLIT;
136             }
137             return;
138         }
139         index = (index + 1) / 2 - 1;
140     }
141 }
142
143 void
144 buddy_free(struct buddy * self, int offset) {
145     assert( offset < (1<< self->level));
146     int left = 0;
147     int length = 1 << self->level;
148     int index = 0;
149
150     for (;;) {
151         switch (self->tree[index]) {
152         case NODE_USED:
153             assert(offset == left);
154             _combine(self, index);
155             return;
156         case NODE_UNUSED:
157             assert(0);
158             return;
159         default:
160             length /= 2;
161             if (offset < left + length) {
162                 index = index * 2 + 1;
163             } else {
164                 left += length;
165                 index = index * 2 + 2;
166             }
167             break;
168         }
169     }
170 }
171
172 int
173 buddy_size(struct buddy * self, int offset) {
174     assert( offset < (1<< self->level));
175     int left = 0;
176     int length = 1 << self->level;
177     int index = 0;
178
179     for (;;) {
180         switch (self->tree[index]) {
181         case NODE_USED:
182             assert(offset == left);
183             return length;
184         case NODE_UNUSED:
185             assert(0);
186             return length;
187         default:
188             length /= 2;
189             if (offset < left + length) {
190                 index = index * 2 + 1;
191             } else {
192                 left += length;
193                 index = index * 2 + 2;
194             }
195             break;
196         }
197     }
198 }
199
200 static void
201 _dump(struct buddy * self, int index , int level) {
202     switch (self->tree[index]) {
203     case NODE_UNUSED:
204         printf("(%d:%d)", _index_offset(index, level, self->level) , 1 << (self->level - level));
205         break;
206     case NODE_USED:
207         printf("[%d:%d]", _index_offset(index, level, self->level) , 1 << (self->level - level));
208         break;
209     case NODE_FULL:
210         printf("{");
211         _dump(self, index * 2 + 1 , level+1);
212         _dump(self, index * 2 + 2 , level+1);
213         printf("}");
214         break;
215     default:
216         printf("(");
217         _dump(self, index * 2 + 1 , level+1);
218         _dump(self, index * 2 + 2 , level+1);
219         printf(")");
220         break;
221     }
222 }
223
224 void
225 buddy_dump(struct buddy * self) {
226     _dump(self, 0 , 0);
227     printf("\n");
228 }
时间: 2024-11-10 09:13:07

Buddy Memorry的相关文章

Buddy system伙伴分配器实现

wikipedia:http://en.wikipedia.org/wiki/Buddy_memory_allocation The buddy memory allocation technique is a memory allocation algorithm that divides memory into partitions to try to satisfy a memory request as suitably as possible. This system makes us

堆管理算法中的Buddy System(伙伴系统)算法

在一个Buddy System算法中,堆管理者只分配特定大小的内存块,成为permitted size.针对每个permitted size,都有一个空闲链表来维护. 一般这些大小会选择2的幂次方,或者斐波那契数列.因为这样会方便地将除最小的那个数之外的其它数都分为两个permitted size之和. 当负责分配内存的堆管理者接受到请求s大小的内存请求时,会讲s对齐到一个permitted size.然后从那个permitted size的空闲链表中分配一块内存给他.如果没有在那个空闲链表中找

PatentTips - Modified buddy system memory allocation

BACKGROUND Memory allocation systems assign blocks of memory on request. A memory allocation system employs an allocator to receive relatively large blocks of memory from an operating system and allocate that memory to satisfy memory requests. Upon r

内存管理算法--Buddy伙伴算法

Buddy算法的优缺点: 1)尽管伙伴内存算法在内存碎片问题上已经做的相当出色,但是该算法中,一个很小的块往往会阻碍一个大块的合并,一个系统中,对内存块的分配,大小是随机的,一片内存中仅一个小的内存块没有释放,旁边两个大的就不能合并.2)算法中有一定的浪费现象,伙伴算法是按2的幂次方大小进行分配内存块,当然这样做是有原因的,即为了避免把大的内存块拆的太碎,更重要的是使分配和释放过程迅速.但是他也带来了不利的一面,如果所需内存大小不是2的幂次方,就会有部分页面浪费.有时还很严重.比如原来是1024

一个程序明白buddy算法

#define method 2 #if  method == 0x00 #include<stdio.h> #include<math.h> /* * struct array_cache * * Per cpu structures * Purpose: * - LIFO ordering, to hand out cache-warm objects from _alloc * - reduce the number of linked list operations * -

Buddy/Sponsor培训?信任的构建

为了更好地阅读体验,欢迎访问博客原文 Buddy/Sponsor是什么? Buddy,正如这个词的意思,小伙伴,好朋友.记得加入ThoughtWorks的时候,大家在公司内部的Session和微信群里喊的最多的是小伙伴.慢慢地我发觉一个现象:几乎每个人都把同事当成自己的小伙伴,大家相处很友好,互帮互助,整个氛围像个大家庭.试想一下,一个刚加入TW的新人,对TW的组织文化和做事方式充满好奇,自己的定位和发展还很茫然的时候,这时候ta被告知:"Hey,你不孤单,你有一个小伙伴,ta将陪伴你度过半年的

buddy算法

buddy算法是用来做内存管理的经典算法,目的是为了解决内存的外碎片.避免外碎片的方法有两种: 1,利用分页单元把一组非连续的空闲页框映射到非连续的线性地址区间. 2,开发适当的技术来记录现存的空闲连续页框块的情况,以尽量避免为满足对小块的请求而把大块的空闲块进行分割. 基于下面三种原因,内核选择第二种避免方法: 在某些情况下,连续的页框确实必要. 即使连续页框的分配不是很必要,它在保持内核页表不变方面所起的作用也是不容忽视的.假如修改页表,则导致平均访存次数增加,从而频繁刷新TLB. 通过4M

内存管理算法--Buddy伙伴算法【转】

转自:http://blog.csdn.net/orange_os/article/details/7392986 Buddy算法的优缺点: 1)尽管伙伴内存算法在内存碎片问题上已经做的相当出色,但是该算法中,一个很小的块往往会阻碍一个大块的合并,一个系统中,对内存块的分配,大小是随机的,一片内存中仅一个小的内存块没有释放,旁边两个大的就不能合并. 2)算法中有一定的浪费现象,伙伴算法是按2的幂次方大小进行分配内存块,当然这样做是有原因的,即为了避免把大的内存块拆的太碎,更重要的是使分配和释放过

Buddy伙伴堆内存管理算法

参考了三篇博客的内容,一篇的界面,一篇的算法和一篇的原理解释,都对代码进行了一定的改变,界面增加了很多部分,内部的话可变性提高,动态适应数据变化. 可以与这三篇博客内容对比着看,便于理解算法. 理解的话看https://blog.csdn.net/orange_os/article/details/7392986 界面参考了https://blog.csdn.net/u014071802/article/details/30716975?utm_source=blogxgwz1 主函数用了下面这