一块内存区,例如128bytes。
在分配一定大小的连续内存空间k时,例如k=32,那么我们就分配给它32;如果k=31,虽然它小于32,但是它大于16,所以仍然分配32;如果k=33,虽然只比32大1,但终究是大于32而且小于64,所以最终是分配364。总结起来,还是需要符合2的幂次方关系,并且只可向上进,不可向下退。
vector<pair<int, int>> free_list[7];
// 7的来源是2的7次方等于128。
free_list[i]的意义在于,它可以分配连续的2的i次方空间给程序。
将free_list[7]初始化为(0,127),表示自己可以分配自己应该分配的连续空间128bytes
而free_list[0~6]为空,表示无法分配自己应该分配的空间。
当确定最终分配的空间大小alloc_mem时,就选择合适的列表位置,即free_list的第几个元素。
即,将alloc_mem 变为 ,根据Index选择free_list[index]。即,1就找free_list[0],2就找free_list[1],4就找free_list[2],8就找free_list[3],...,128就找free_list[7]。
######################## 分配内存 ########################
开始分配空间,根据32找到free_list[5],
allocate(32);
如果free_list[5]正好有空间,则分配给它就可以。
如果free_list[5]为空,故一直向上寻找空间,直到free_list[n]>0。这时,free_list[n]空间一定大于等于所需空间的2倍,此时将free_list[n]空间分半后给free_list[n-1],free_list[n-1]保留后半部分,free_list[n-1]把前半部分再分半后交给free[n-2],free_list[n-2]保留后半部分,free_list[n-2]把前半部分再分半后交给free[n-3],...,一直到交给free_list[i]后,free_list[i]保留后半部分,free_list[i]把前半部分分配出去给alloc_mem。从n-1到i,他们接收到的空间都是已经分为两半的空间,相同之处都是保留了后半部分空间按,区别在于最后一个i将前半部分分配给alloc_mem了,而n-1他们都是把分配给他们的前半部分再次分半,交给下一个阶段,即n-1分半后给n-2,n-2分半后给n-3,直到i不再将前半部分分半,而是直接分配给alloc_mem,到此,分配结束。
如果free_list[5]为空,并一直向上寻找空间不得,就显示无法分配空间。
第一次分配形象化描述为:
free_list[ ] | 初始状态 | allocate(32) |
0 | ||
1 | ||
2 | ||
3 | ||
4 | ||
5 | [32,63] | |
6 | [64,127] | |
7 | [0,127] | |
mp | mp[0]=32 |
map<int, int> mp;
// mp[start]=size,表示内存从start开始的连续size大小空间已经分配
之后继续分配空间
allocate(7);
初始状态 | allocate(32) | allocate(7) | |
0 | |||
1 | |||
2 | |||
3 | [40,47] | ||
4 | [48,63] | ||
5 | [32,63] | ||
6 | [64,127] | [64,127] | |
7 | [0,127] | ||
mp | mp[0]=32 | mp[0]=32 mp[32]=8 |
再次分配空间
allocate(2);
allocate(64);
allocate(56);
初始状态 | allocate(32) | allocate(7) | allocate(2) | allocate(64) | allocate(56) | |
0 | ||||||
1 | [42,43] | [42,43] | ||||
2 | [44,47] | [44,47] | ||||
3 | [40,47] | |||||
4 | [48,63] | [48,63] | [48,63] | |||
5 | [32,63] | |||||
6 | [64,127] | [64,127] | [64,127] | |||
7 | [0,127] | failed | ||||
mp | mp[0]=32 | mp[0]=32 mp[32]=8 | mp[0]=32 mp[32]=8 mp[40]=2 | mp[0]=32 mp[32]=8 mp[40]=2 mp[64]=64 |
规律:首先根据alloc_mem= 找到index,例如allocate(7)时,index就等于3。然后在之前allocate(32)的基础上,就一直向上找第一个不为空的free_list[i],此时i=5,然后把free_list[[5]减半给下一个,一直重复到我们的index=3,然后free_list[3]就保留后半部分空间,前半部分分配出去就行了。如果一直向上找都为空,即分配allocate(56)时,自己的index=6,但是向上找都是空,那么就分配失败。
######################## 释放内存 ########################
当一个进程结束时,就把他的空间释放掉,根据mp[start]=size可以轻松释放占用的内存。
下一步就是合并空闲内存。即自己释放的内存一定是2的i次方,那么,free_list[i]它也可以分配空间,两者的空间大小一样,那么如果释放的内存和free_list[i]可以分配的内存是连续的空间,就可以合并起来,把内存变大两倍,free_list[i]就晋级为free_list[i+1]了。再进一步,如果free_list[i+1]也有内存可以分配,并且和我们的连续,就再来一次合并,一直到不可以为止。