简易伙伴系统的实现

最近项目上涉及内存管理,继而了解了伙伴系统,发现很有意思,于是实现了一版简单的,效率和参数校验上都没有太理会,仅仅正向测试了下,分享给大家,Github完整源码见如下链接(源码有注释图,更加清晰):
简易版buddySystem
手机版复制地址打开:https://github.com/CallonHuang/BuddySystem

两个核心的函数如下:

int BuddyAlloc(BUDDY_TYPE buddy_type, void **viraddr)
{
    int i = 0;
    BUDDY_INFO* target_node;
    if (free_area[buddy_type].list.count != 0)
    {
        target_node = (BUDDY_INFO *)free_area[buddy_type].list.node.next;
		*viraddr = target_node->start;
        ListDelete(&free_area[buddy_type].list, (NODE *)target_node);
        free(target_node);
    }
    else
    {
        for (i = buddy_type; i < BUDDY_TYPE_MAX; i++)
        {
            if (free_area[i].list.count != 0)
            {
                break;
            }
        }
        if (i != BUDDY_TYPE_MAX)
        {
            SplitNode(buddy_type, i);
            return BuddyAlloc(buddy_type, viraddr);
        }
        else
        {
            return -1;
        }
    }
    return 0;
}

void BuddyRecycle(BUDDY_TYPE buddy_type, void *viraddr)
{
    int i = 0, bMerged = 0;
    BUDDY_INFO* cur_node = NULL;
    BUDDY_INFO* target_node = (BUDDY_INFO *)malloc (sizeof(BUDDY_INFO));
    target_node->start = viraddr;
    for (cur_node = (BUDDY_INFO*)free_area[buddy_type].list.node.next; 
        cur_node != (BUDDY_INFO*)&free_area[buddy_type].list.node; 
        cur_node = (BUDDY_INFO*)cur_node->list.node.next)
    {
        if (cur_node->start > viraddr)
        {
            break;
        }
    }
    ListInsert(&free_area[buddy_type].list, (NODE *)target_node, (NODE *)cur_node);
    for (i = buddy_type; i < BUDDY_TYPE_MAX-1; )
    {	
        if (free_area[i].list.count > 1)
        {
            for (cur_node = (BUDDY_INFO*)free_area[i].list.node.next; 
                cur_node->list.node.next != &free_area[i].list.node; 
                cur_node = (BUDDY_INFO*)cur_node->list.node.next)
            {
                if (MergeNode(i, cur_node, (BUDDY_INFO*)cur_node->list.node.next) == 0)
                {
                    bMerged = 1;
                    break;
                }
            }
        }
        if (!bMerged)
            i++;
        else
            bMerged = 0;
    }
}

分别是分配和回收,从中可以看到伙伴系统的机制:

  1. 分配:若所需要的内存块链表中没有node,则向上请求更大内存的链表,直到请求到后,逐级分解直至有所需要的内存块,最后分配;
  2. 回收:找到合适的地方插入(保证节点是地址有序的),然后从该节点所在链表进行遍历,查看能否合并,并且逐级向上查看更大内存中是否存在可以合并的连续内存块,合并又有两个原则:必须连续且到起始的偏移必须是高阶内存的整数倍。
假设系统的可利用空间容量为2m个字,则系统开始运行时,整个内存区是一个大小为2m的空闲分区。在系统运行过程中,由于不断的划分,可能会形成若干个不连续的空闲分区,将这些空闲分区根据分区的大小进行分类,对于每一类具有相同大小的所有空闲分区,单独设立一个空闲分区双向链表。这样,不同大小的空闲分区形成了k(0≤k≤m)个空闲分区链表。 当需要为进程分配一个长度为n的存储空间时,首先计算一个i值,使2i-1<n≤2i,然后在空闲分区大小为2i的空闲分区链表中查找。若找到,即把该空闲分区分配给进程。否则,表明长度为2i的空闲分区已经耗尽,则在分区大小为2i+1的空闲分区链表中寻找。若存在2i+1的一个空闲分区,则把该空闲分区分为相等的连个分区,这两个分区称为一对伙伴,其中的一个分区用于分配,而把另一个加入分区大小为2i的空闲分区链表中。若大小为2i+1的空闲分区不存在,则需要查找大小为2i+2的空闲分区,若找到则对其进行两次分割:第一次,将其分割为大小为2i+1的两个分区,一个用于分配,一个加入到大小为2i+1空闲分区链表中;第二次,将第一次用于分配的空闲分区分割为2i的两个分区,一个用于分配,一个加入到大小为2i空闲分区链表中。若仍然找不到,则继续查找大小为2i+3的空闲分区,以此类推。由此可见,在最坏的情况下,可能需要对2k的空闲分区进行k次分割才能得到所需分区。 与一次分配可能要进行多次分割一样,一次回收也可能要进行多次合并,如回收大小为2i的空闲分区时,若事先已存在2i的空闲分区时,则应将其与伙伴分区合并为大小为2i+1的空闲分区,若事先已存在2i+1的空闲分区时,又应继续与其伙伴分区合并为大小为2i+2的空闲分区,依此类推。 2.2 伙伴系统的需求 根据伙伴系统算法的思想,我们组对本系统的功能划分为3种: ⑴ 根据伙伴系统算法分配内存 ⑵ 根据伙伴系统算法回收内存 ⑶ 实时查看内存使用的情况
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值