Buddy System 伙伴系统 python实现

import math

achieve = False
achieve2 = False
# 基本节点
class Node(object):
    def __init__(self, size, depth):
        self.ID = ""
        self.status = 0  # 初始空闲
        self.size = size # 初始大小为0
        self.left = None
        self.right = None
        self.depth = depth   # 此节点创建的深度


class Operation(object):
    def __init__(self, maxlen, minlen):
        self.maxlen = int(math.pow(2, maxlen))
        self.minlen = int(math.pow(2, minlen))
        self.result = []
        self.root = Node(self.maxlen, 0)    # 初始化节点

    def allocate(self, size, ID):
        global achieve
        global achieve2
        level = 0     # 裂变的层数
        # print('maxlen',self.maxlen,'root',root.size)

        # 获取此节点应该在的深度
        for i in range(10):
            if size <= self.maxlen//math.pow(2,i) and size > self.maxlen//math.pow(2,i+1):
                level = i    # 获取裂变的层数或者搜索的深度
                break
        
        print("搜索深度为", level)
        print('将要分配的节点是:', ID)

        # 未分配状态下建立二叉树
        if self.root.left is None and self.root.right is None:
            p = self.root
            for i in range(level):
                p.status = 1
                p.left = Node(p.size/2, i+1)
                p.right = Node(p.size/2, i+1)
                p = p.left
            p.status = 1    # 最后一个分配的节点状态变为已分配
            p.ID = ID
            
            print("%8s %5s %5s %2s" % ('size', 'depth', 'status', 'ID'))
            self.printMemMap(self.root)

        else:    
            # 已建立二叉树情况下的二叉树
            achieve = False
            achieve2 = False
            print('\n 已经有建立的伙伴树')
            self.LRD(self.root, 0, level, 0, ID)

            print("%8s %5s %5s %2s" % ('size','depth','status','ID'))
            self.printMemMap(self.root)

            if achieve == True:
                print('在已经建立的二叉树已找到空闲节点且已分配')
            else:
                print('\n在已建立的二叉树上未找到空闲的节点,尝试分配')

                # 找到此节点以上的任意一层的空闲节点

                self.LRD2(self.root, 0, level-1, 0, ID)

                print("%8s %5s %5s %2s" % ('size','depth','status','ID'))
                self.printMemMap(self.root)

                if achieve2 == False:
                    print('分配失败,请等待内存释放')
                else:
                    print('分配成功')

    # 释放
    def release(self, ID):
        print('\n释放过程。。。', '释放节点为', ID)
        self.searchAll(self.root, ID)
        self.releaseWay(self.root)
        print("%8s %5s %5s %2s" % ('size','depth','status','ID'))
        self.printMemMap(self.root)
 
    def searchAll(self, root, ID):
        if root.ID != ID:
            if root.left is not None:
                self.searchAll(root.left, ID)
            if root.right is not None:
                self.searchAll(root.right, ID)
        else:
            root.status = 0
            root.ID = ''
            print('已成功释放')
    
    def releaseWay(self, root):
        if root.left is not None and root.right is not None:
            if root.left.status == 0 and root.right.status == 0:
                root.left = None
                root.right = None
                root.status = 0
        if root.left is not None:
            self.releaseWay(root.left)
        if root.right is not None:
            self.releaseWay(root.right)



    # 树能满足的情况下
    def LRD(self, node, depth, level, flag, ID):
        global achieve
        if flag == 0:
            # print('depth', depth,' level', level, 'size', node.size)
            if depth < level:
                if node.left is not None:
                    self.LRD(node.left, depth+1, level, flag, ID)
                if node.right is not None:
                    self.LRD(node.right, depth+1, level, flag, ID)
            if depth == level:
                if node.status == 0:
                    node.status = 1
                    flag = 1
                    achieve = True
                    node.ID = ID

    # 遍历
    def LRD2(self, node, depth, level, flag, ID):
        global achieve2
        if flag == 0 and achieve2 == False:
            if depth < level:
                if node.left is not None:
                    self.LRD2(node.left, depth+1, level, flag, ID)
                if node.right is not None:
                    self.LRD2(node.right, depth+1, level, flag, ID)
            if depth == level and node.status == 0:
                flag = 1
                node.status = 1
                achieve2 = True
                node.left = Node(node.size/2, depth+1)
                node.right = Node(node.size/2, depth+1)
                node.left.ID = ID
                node.left.status = 1
            # print('Achieve2',achieve2)


    def printMemMap(self, node):
        print("%8s %5s %5s %2s" % (node.size, node.depth, node.status, node.ID))
        if node.left is not None:
            self.printMemMap(node.left)
        if node.right is not None:
            self.printMemMap(node.right)
            


test = Operation(10, 1)

test.allocate(100, 'ID1')
test.allocate(240, 'ID2')
test.allocate(64, 'ID3')
test.allocate(256, 'ID4')
test.release('ID2')
test.release('ID1')
test.allocate(75, 'ID5')
test.release('ID3')
test.release('ID4')

 

假设系统的可利用空间容量为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、付费专栏及课程。

余额充值