【问题标题】:Buddy Allocation Algorithm - Heap Extension好友分配算法 - 堆扩展
【发布时间】:2013-10-30 16:46:50
【问题描述】:

这是对我实施好友分配方案的第二次询问,第一个问题是here,这也解释了好友分配实际上是什么。在标准实现中,从 2^i 的大块开始,其中 i 是一个整数,它适用于静态堆大小(在这种情况下,整个堆是最大的块)。

我的问题取决于处理动态调整堆大小的实现,其中堆大小从 0 开始。目前,当最高顺序 i 时,无法在空闲列表中找到块(a空闲块列表),我调用扩展堆大小以占用这个最高阶块。

问题是我不确定这个导数是否会破坏伙伴系统中的不变量,即计算给定地址的伙伴块地址。这可以简单地通过翻转第 i 阶位来计算。这个计算的解释在我之前的问题中。当我实施这个方案时,有时我会返回错误的好友地址。

【问题讨论】:

  • 您为了增加堆大小而进行了哪个调用?
  • @fvdalcin 这是一个自定义调用,它所做的只是将指向堆后部的指针移动到一个大小参数的后面,并返回一个指向这个新分配块中第一个地址的 void 指针。
  • AFAIK 伙伴方案假定堆是连续的。通常,扩展堆要么破坏该不变量,要么必须移动堆的现有部分并更新所有指针,这在大多数环境中是不可能的(那些您可以识别 all 指针并更新它们的环境引用新的堆区域)。
  • @delnan 即使您每次仅将堆扩展为最大订单大小的固定数量?这不会创建两个单独的“伙伴树”吗?

标签: c++ c algorithm memory memory-management


【解决方案1】:

我不确定您是否可以在一些块已经分配之后增加堆大小。我认为您将不得不按照分配算法增加堆并重新分配所有块,但现在考虑您的新堆大小。

【讨论】:

    【解决方案2】:
        #include <stdio.h>
    
    typedef struct X 
    {
        unsigned int address;
        int empty;
        int id_req;//id_req
        int allow;
    } Block;
    
    typedef struct Y  
    {
        int enz;
        int id_req;//req_id
        int ok;
    } Defer;
    
    unsigned int block_sizes[8] = {0};
    unsigned int memSize;
    unsigned int allcSize;
    
    Block blocks[8][128];
    int num_blocks[8];
    
    int defer_pointer = 0;
    Defer defers[100];
    
    int main(int argc, char **argv)
    {
        int x, y, z; 
    
        for(x = 0;x < 100;x++)
            defers[x].ok = 1;
    
        for(x = 0;x < 8;x++)
            for(y = 0;y < 128;y++)
                blocks[x][y].empty = blocks[x][y].allow = 0;
    
        scanf("%u", &memSize);
        scanf("%u", &allcSize);
    
        block_sizes[0] = allcSize;
        for(x = 0;x+1 < 8;x++)
            if(block_sizes[x] == memSize)
                break;
            else
                block_sizes[x+1] = block_sizes[x]*2;
    
        blocks[x][0].address = 0;
        blocks[x][0].empty = 1;
        num_blocks[x] = 1;
        for(;x > 0;x--)
        {
            num_blocks[x-1] = num_blocks[x]*2;
    
            for(y=0;y < num_blocks[x];y++)
            {
                blocks[x-1][2*y].address = blocks[x][y].address;
                blocks[x-1][2*y+1].address = blocks[x][y].address + block_sizes[x-1];
            }
        }
    
        while(scanf("%d", &z) != EOF)
        {
            char op = getchar();
            while(op != '-' && op != '+') op = getchar();
    
            if(op == '+')
            {
                unsigned int size;
                scanf("%u", &size);
                printf("Request ID %d: allocates %u byte%s.\n", z, size, size == 1 ? "" : "s");
    
                int enz = 0;
                while(block_sizes[enz] < size)
                    enz++;
    
                unsigned int address;
                if(allocate(enz, z, &address)) 
                {
                    printf("\tSuccess; addr = 0x%08x.\n", address);
                }
                else
                {
                    printf("\tRequest deferred.\n");
                    defers[defer_pointer].ok = 0;
                    defers[defer_pointer].enz = enz;
                    defers[defer_pointer].id_req = z;
                    defer_pointer++;
                }
            }
            else
            {
                printf("Request ID %d: deallocate.\n", z);
    
                int success = 0;
                for(x = 0;x < 8 && block_sizes[x] != 0 && success != 1;x++)
                    for(y = 0;y < num_blocks[x] && success != 1;y++)
                        if(blocks[x][y].allow)
    
                            if (blocks[x][y].id_req == z)
                            {
                                blocks[x][y].allow = 0;
                                blocks[x][y].empty = 1;
                                success = 1;
                            }
    
                x--;y--;
    
                if(success)
                    printf("\tSuccess.\n");
                else
                    continue;
                // the buddy system
    
                while(x < 8 && num_blocks[x] > 1)
                {
                    int buddy = (blocks[x][y].address / block_sizes[x]) %2 == 0 ? (y+1) : (y-    1);
    
                    if(blocks[x][buddy].empty)
                    {
                        blocks[x][y].empty = 0;
                        blocks[x][buddy].empty = 0;
    
                        blocks[x+1][y/2].empty = 1;
                        x++;
                        y /= 2;
                    }
                    else
                    {
                        break;
                    }
                }
    
                for(x = 0;x < defer_pointer;x++)
                    if(!defers[x].ok)
                    {
                        unsigned int address;
                        if(allocate(defers[x].enz, defers[x].id_req, &address))
                        {
                            defers[x].ok = 1;
                            printf("\tDeferred request %d allocated; addr = 0x%08x\n", defers[x].id_req, address);
                        }
                    }
            }
        }
    
        return 0;
    }
    
    int allocate(int enz, int id_req, unsigned int *address)
    {
        int x, y, ret = 0;
        for(x = enz;x < 8 && block_sizes[x] != 0 && ret == 0;x++)
            for(y = 0;y < num_blocks[x] && ret == 0;y++)
                if(blocks[x][y].empty)
                    ret = 1;
        x--;y--;
        if(ret == 0)
            return 0;
    
        while(x != enz)
        {
            blocks[x][y].empty = 0;
    
            blocks[x-1][2*y].empty = 1;
            blocks[x-1][2*y+1].empty = 1;
    
            x = x-1;
            y = 2*y;
        }
    
        blocks[x][y].empty = 0;
        blocks[x][y].id_req = id_req;
        blocks[x][y].allow = 1;
        *address = blocks[x][y].address;
    }
    

    【讨论】:

    • 上面的程序显示了伙伴系统的基本实现,其中显示了伙伴分配的堆扩展。
    • 希望对某人有所帮助
    猜你喜欢
    • 1970-01-01
    • 2022-01-10
    • 2012-05-13
    • 1970-01-01
    • 2013-09-28
    • 2020-01-22
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多