📜  好友内存分配计划|组 1(分配)

📅  最后修改于: 2022-05-13 01:56:11.639000             🧑  作者: Mango

好友内存分配计划|组 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)