好友内存分配计划|组 1(分配)
先决条件 - 好友系统
问题:编写一个程序来实现操作系统中内存分配的伙伴系统。
解释 -
伙伴系统实现如下 - 一个空闲节点列表,所有可能的 2 次幂,始终保持(因此,如果总内存大小为 1 MB,我们将有 20 个空闲列表来跟踪一个块大小为 1 字节,1 为 2 字节,下一个为 4 字节,依此类推)。
当分配请求到来时,我们寻找比它大的最小块。如果在空闲列表中找到这样的块,则分配完成(例如,请求为 27 KB,并且跟踪 32 KB 块的空闲列表中至少有一个元素),否则我们向上遍历空闲列表,直到我们找到一个足够大的块。然后我们继续分裂它在两大块,一个是增加了一个空闲列表(小尺寸的),一个,直到我们达到目标遍历下来的树和请求存储块返回给用户。如果没有这样的分配是可能的,我们简单地返回 null。
例子:
让我们通过跟踪大小为 128 KB 的内存块来看看算法是如何进行的。最初,空闲列表是:{}, {}, {}, {}, {}, {}, {}, { (0, 127) }
- 请求: 32 字节
没有找到这样的块,所以我们向上遍历,将0-127块拆分为0-63、64-127;我们添加 64-127 以列出跟踪 64 字节块并向下传递 0-63;再次分为0-31和32-63;由于我们找到了所需的块大小,我们添加 32-63 以列出跟踪 32 字节的块并将 0-31 返回给用户。
列表为:{}, {}, {}, {}, {}, { (32, 63) }, { (64, 127) }, {} - 请求: 7 个字节
没有找到这样的块-将块32-63拆分为两个块,即32-47和48-63;然后将 32-47 分成 32-39 和 40-47;最后,返回32-39给用户(发生1字节的内部碎片)
列表为:{}, {}, {}, { (40, 47) }, { (48, 63) }, {}, { (64, 127) }, {} - 请求: 64 字节
直接分配内存段 64-127,因为它已经存在。
列表为:{}, {}, {}, { (40, 47) }, { (48, 63) }, {}, {}, {} - 请求:56 字节
结果:未分配
结果如下:
图 – Buddy Allocation-128 显示下一个可能块的起始地址(如果主内存大小增加)
执行 -
C++
#include
using namespace std;
// Size of vector of pairs
int size;
// Global vector of pairs to store
// address ranges available in free list
vector> free_list[100000];
// Map used as hash map to store the starting
// address as key and size of allocated segment
// key as value
map mp;
void initialize(int sz)
{
// Maximum number of powers of 2 possible
int n = ceil(log(sz) / log(2));
size = n + 1;
for(int i = 0; i <= n; i++)
free_list[i].clear();
// Initially whole block of specified
// size is available
free_list[n].push_back(make_pair(0, sz - 1));
}
void allocate(int sz)
{
// Calculate index in free list
// to search for block if available
int n = ceil(log(sz) / log(2));
// Block available
if (free_list[n].size() > 0)
{
pair temp = free_list[n][0];
// Remove block from free list
free_list[n].erase(free_list[n].begin());
cout << "Memory from " << temp.first
<< " to " << temp.second << " allocated"
<< "\n";
// map starting address with
// size to make deallocating easy
mp[temp.first] = temp.second -
temp.first + 1;
}
else
{
int i;
for(i = n + 1; i < size; i++)
{
// Find block size greater than request
if(free_list[i].size() != 0)
break;
}
// If no such block is found
// i.e., no memory block available
if (i == size)
{
cout << "Sorry, failed to allocate memory \n";
}
// If found
else
{
pair temp;
temp = free_list[i][0];
// Remove first block to split it into halves
free_list[i].erase(free_list[i].begin());
i--;
for(; i >= n; i--)
{
// Divide block into twwo halves
pair pair1, pair2;
pair1 = make_pair(temp.first,
temp.first +
(temp.second -
temp.first) / 2);
pair2 = make_pair(temp.first +
(temp.second -
temp.first + 1) / 2,
temp.second);
free_list[i].push_back(pair1);
// Push them in free list
free_list[i].push_back(pair2);
temp = free_list[i][0];
// Remove first free block to
// further split
free_list[i].erase(free_list[i].begin());
}
cout << "Memory from " << temp.first
<< " to " << temp.second
<< " allocated" << "\n";
mp[temp.first] = temp.second -
temp.first + 1;
}
}
}
// Driver code
int main()
{
// Uncomment following code for interactive IO
/*
int total,c,req;
cin>>total;
initialize(total);
while(true)
{
cin>>req;
if(req < 0)
break;
allocate(req);
}*/
initialize(128);
allocate(32);
allocate(7);
allocate(64);
allocate(56);
return 0;
}
// This code is contributed by sarthak_eddy
Java
import java.io.*;
import java.util.*;
class Buddy {
// Inner class to store lower
// and upper bounds of the allocated memory
class Pair
{
int lb, ub;
Pair(int a, int b)
{
lb = a;
ub = b;
}
}
// Size of main memory
int size;
// Array to track all
// the free nodes of various sizes
ArrayList arr[];
// Else compiler will give warning
// about generic array creation
@SuppressWarnings("unchecked")
Buddy(int s)
{
size = s;
// Gives us all possible powers of 2
int x = (int)Math.ceil(Math.log(s) / Math.log(2));
// One extra element is added
// to simplify arithmetic calculations
arr = new ArrayList[x + 1];
for (int i = 0; i <= x; i++)
arr[i] = new ArrayList<>();
// Initially, only the largest block is free
// and hence is on the free list
arr[x].add(new Pair(0, size - 1));
}
void allocate(int s)
{
// Calculate which free list to search to get the
// smallest block large enough to fit the request
int x = (int)Math.ceil(Math.log(s) / Math.log(2));
int i;
Pair temp = null;
// We already have such a block
if (arr[x].size() > 0)
{
// Remove from free list
// as it will be allocated now
temp = (Pair)arr[x].remove(0);
System.out.println("Memory from " + temp.lb
+ " to " + temp.ub + " allocated");
return;
}
// If not, search for a larger block
for (i = x + 1; i < arr.length; i++) {
if (arr[i].size() == 0)
continue;
// Found a larger block, so break
break;
}
// This would be true if no such block was found
// and array was exhausted
if (i == arr.length)
{
System.out.println("Sorry, failed to allocate memory");
return;
}
// Remove the first block
temp = (Pair)arr[i].remove(0);
i--;
// Traverse down the list
for (; i >= x; i--) {
// Divide the block in two halves
// lower index to half-1
Pair newPair = new Pair(temp.lb, temp.lb
+ (temp.ub - temp.lb) / 2);
// half to upper index
Pair newPair2 = new Pair(temp.lb
+ (temp.ub - temp.lb + 1) / 2, temp.ub);
// Add them to next list
// which is tracking blocks of smaller size
arr[i].add(newPair);
arr[i].add(newPair2);
// Remove a block to continue the downward pass
temp = (Pair)arr[i].remove(0);
}
// Finally inform the user
// of the allocated location in memory
System.out.println("Memory from " + temp.lb
+ " to " + temp.ub + " allocated");
}
public static void main(String args[]) throws IOException
{
int initialMemory = 0, val = 0;
// Uncomment the below section for interactive I/O
/*Scanner sc=new Scanner(System.in);
initialMemory = sc.nextInt();
Buddy obj = new Buddy(initialMemory);
while(true)
{
val = sc.nextInt();// Accept the request
if(val <= 0)
break;
obj.allocate(val);// Proceed to allocate
}*/
initialMemory = 128;
// Initialize the object with main memory size
Buddy obj = new Buddy(initialMemory);
obj.allocate(32);
obj.allocate(7);
obj.allocate(64);
obj.allocate(56);
}
}
C#
using System;
using System.Collections.Generic;
public class Buddy
{
// Inner class to store lower
// and upper bounds of the
// allocated memory
class Pair
{
public int lb, ub;
public Pair(int a, int b)
{
lb = a;
ub = b;
}
}
// Size of main memory
int size;
// Array to track all
// the free nodes of various sizes
List []arr;
// Else compiler will give warning
// about generic array creation
Buddy(int s)
{
size = s;
// Gives us all possible powers of 2
int x = (int)Math.Ceiling(Math.Log(s) /
Math.Log(2));
// One extra element is added
// to simplify arithmetic calculations
arr = new List[x + 1];
for (int i = 0; i <= x; i++)
arr[i] = new List();
// Initially, only the largest block is free
// and hence is on the free list
arr[x].Add(new Pair(0, size - 1));
}
void allocate(int s)
{
// Calculate which free list to search
// to get the smallest block
// large enough to fit the request
int x = (int)Math.Ceiling(Math.Log(s) /
Math.Log(2));
int i;
Pair temp = null;
// We already have such a block
if (arr[x].Count > 0)
{
// Remove from free list
// as it will be allocated now
temp = (Pair)arr[x][0];
arr[x].RemoveAt(0);
Console.WriteLine("Memory from " + temp.lb +
" to " + temp.ub + " allocated");
return;
}
// If not, search for a larger block
for (i = x + 1; i < arr.Length; i++)
{
if (arr[i].Count == 0)
continue;
// Found a larger block, so break
break;
}
// This would be true if no such block
// was found and array was exhausted
if (i == arr.Length)
{
Console.WriteLine("Sorry, failed to" +
" allocate memory");
return;
}
// Remove the first block
temp = (Pair)arr[i][0];
arr[i].RemoveAt(0);
i--;
// Traverse down the list
for (; i >= x; i--)
{
// Divide the block in two halves
// lower index to half-1
Pair newPair = new Pair(temp.lb, temp.lb +
(temp.ub - temp.lb) / 2);
// half to upper index
Pair newPair2 = new Pair(temp.lb + (temp.ub -
temp.lb + 1) / 2, temp.ub);
// Add them to next list which is
// tracking blocks of smaller size
arr[i].Add(newPair);
arr[i].Add(newPair2);
// Remove a block to continue
// the downward pass
temp = (Pair)arr[i][0];
arr[i].RemoveAt(0);
}
// Finally inform the user
// of the allocated location in memory
Console.WriteLine("Memory from " + temp.lb +
" to " + temp.ub + " allocated");
}
// Driver Code
public static void Main(String []args)
{
int initialMemory = 0;
initialMemory = 128;
// Initialize the object with main memory size
Buddy obj = new Buddy(initialMemory);
obj.allocate(32);
obj.allocate(7);
obj.allocate(64);
obj.allocate(56);
}
}
// This code is contributed by 29AjayKumar
Javascript
输出:
Memory from 0 to 31 allocated
Memory from 32 to 39 allocated
Memory from 64 to 127 allocated
Sorry, failed to allocate memory
时间复杂度——
如果主内存大小为n ,我们有 log(n) 个不同的 2 次幂,因此在跟踪空闲列表的数组(在代码中命名为arr )中有 log(n) 个元素。要分配一个块,我们只需要向上和向下遍历数组一次,因此时间复杂度为O(2log(n))或简单地为O(logn)