python实现操作系统学习中的动态内存分配算法

按书上的,算法有五种,最先适应、最佳适应、最坏适应、下次适应、快速适应(或者说是伙伴算法,其实linux的伙伴算法复杂很多)。只是作业的一次记录,写的比较臃肿

代码:

import math
import operator
import numpy


class FreeAreaTable:
    # 空闲区表
    def __init__(self, start, length):
        """
        :param start:   起址
        :param length:  长度
        """
        self.start = start
        self.length = length


class AllocatedTable:
    # 已分配表
    def __init__(self, start, length, name, mem_length):
        """
        :param start:   起址
        :param length:  长度
        :param name:    名称
        :param mem_length: 实际分配的内存长度
        """
        self.start = start
        self.length = length
        self.name = name
        self.mem_length = mem_length

class MemHandle:
    free_table_list = []  # 空闲区列表
    allocated_table_list = []  # 已分配区列表
    next_location = 0  # 下次适应的位置

    @classmethod
    def insert_free_table(cls, start, length):
        """
        为空闲区表插入一个表项
        :param start:   起址
        :param length:  长度
        :return:
        """
        free_table = FreeAreaTable(start, length)
        cls.free_table_list.append(free_table)

    @classmethod
    def insert_allocated_table(cls, start, length, name):
        """
        为已分配表插入一个表项
        :param start: 起址
        :param length: 长度
        :param name: 名称
        :return:
        """
        allocated_table = AllocatedTable(start, length, name, mem_length=length)
        cls.allocated_table_list.append(allocated_table)

    @classmethod
    def recovered_memory(cls, start, length):
        """
        回收内存并合并相邻的内存,修改后,空闲分区表的排序是按照地址排序
        :param start:  起址
        :param length:  长度
        :return:True or False
        """
        state = 0
        for i in range(len(cls.allocated_table_list)):
            if cls.allocated_table_list[i].start == start:
                # 移除已分配表 项
                cls.allocated_table_list.pop(i)
                state = 1
                break
        if state == 0:
            return False
        # 将回收的内存插入空闲分区表
        cls.insert_free_table(start, length)
        # 将空闲分区表先按地址小到大排序
        cmpfun = operator.attrgetter('start')
        cls.free_table_list.sort(key=cmpfun)
        # 内存合并,倒序遍历
        for i in range(len(cls.free_table_list) - 1, 0, -1):
            if cls.free_table_list[i - 1].start + cls.free_table_list[i - 1].length == cls.free_table_list[i].start:
                cls.free_table_list[i - 1].length += cls.free_table_list[i].length
                cls.free_table_list.pop(i)
        return True

    @classmethod
    def recovered_memory(cls, name):
        """
        回收内存并合并相邻的内存,修改后,空闲分区表的排序是按照地址排序
        :param name: 作业名称
        :return:True or False
        """
        for i in cls.allocated_table_list:
            if i.name==name:
                start=i.start
                length=i.length
        state = 0
        for i in range(len(cls.allocated_table_list)):
            if cls.allocated_table_list[i].start == start:
                # 移除已分配表 项
                cls.allocated_table_list.pop(i)
                state = 1
                break
        if state == 0:
            return False
        # 将回收的内存插入空闲分区表
        cls.insert_free_table(start, length)
        # 将空闲分区表先按地址小到大排序
        cmpfun = operator.attrgetter('start')
        cls.free_table_list.sort(key=cmpfun)
        # 内存合并,倒序遍历
        for i in range(len(cls.free_table_list) - 1, 0, -1):
            if cls.free_table_list[i - 1].start + cls.free_table_list[i - 1].length == cls.free_table_list[i].start:
                cls.free_table_list[i - 1].length += cls.free_table_list[i].length
                cls.free_table_list.pop(i)
        return True

    @classmethod
    def print_free_table(cls):
        """
        打印空闲分区表
        :return:
        """
        print('free table:')
        for i in cls.free_table_list:
            print('start:', i.start, ' length:', i.length)
        print('====================================')

    @classmethod
    def print_allocated_table(cls):
        """
        打印已分配表
        :return:
        """
        print('allocated table:')
        for i in cls.allocated_table_list:
            print('start:', i.start, ' length:', i.length, 'name:', i.name)
        print('====================================')

    @classmethod
    def first_fit(cls, length, name):
        """
        根据首次适应算法,为作业分配内存,返回true或false
        :param length: 作业长度
        :param name: 作业名称
        :return True False
        """
        # 由于内存回收后是按照地址大小排序,因此不用再对列表排序
        for i in range(len(cls.free_table_list)):
            start = cls.free_table_list[i].start
            free_length = cls.free_table_list[i].length
            if free_length >= length:
                if free_length == length:
                    # 如果内存大小刚好等于作业内存大小,插入已分配表,直接移除这一个空闲列表项
                    cls.insert_allocated_table(start, length, name)
                    cls.free_table_list.pop(i)
                    return True
                elif free_length > length:
                    # 如果大于,则分配出去并修改
                    cls.insert_allocated_table(start, length, name)
                    cls.free_table_list[i].start += length
                    cls.free_table_list[i].length -= length
                    return True

        print('内存不足,内存分配失败!!!')
        return False

    @classmethod
    def next_fit(cls, length, name):
        """
        根据下次适应算法,为作业分配内存,返回ture或false
        :param length:作业长度
        :param name: 作业名称
        :return True False
        """

        list_length = len(cls.free_table_list)
        first = cls.next_location
        while cls.next_location <= list_length:
            # 由于内存回收后是按照地址大小排序,因此不用再对列表排序
            start = cls.free_table_list[cls.next_location].start
            free_length = cls.free_table_list[cls.next_location].length
            if free_length >= length:
                if free_length == length:
                    # 如果内存大小刚好等于作业内存大小,插入已分配表,直接移除这一个空闲列表项
                    cls.insert_allocated_table(start, length, name)
                    cls.free_table_list.pop(cls.next_location)
                    return True
                elif free_length > length:
                    # 如果大于,则分配出去并修改
                    cls.insert_allocated_table(start, length, name)
                    cls.free_table_list[cls.next_location].start += length
                    cls.free_table_list[cls.next_location].length -= length
                    return True
            else:
                # 位置加一并求余
                cls.next_location += 1
                cls.next_location %= list_length
                if cls.next_location == first:
                    break
        print('内存不足,内存分配失败!!!')
        return False

    @classmethod
    def best_fit(cls, length, name):
        """
        根据最优适应算法,选取最小的内存区为作业分配内存,返回ture或false
        :param length:作业长度
        :param name: 作业名称
        :return: True False
        """
        # 由于内存回收后是按照地址大小排序,因此重新对列表根据内存大小排序
        cmpfun = operator.attrgetter('length')
        cls.free_table_list.sort(key=cmpfun)

        for i in range(len(cls.free_table_list)):
            start = cls.free_table_list[i].start
            free_length = cls.free_table_list[i].length
            if free_length >= length:
                if free_length == length:
                    # 如果内存大小刚好等于作业内存大小,插入已分配表,直接移除这一个空闲列表项
                    cls.insert_allocated_table(start, length, name)
                    cls.free_table_list.pop(i)
                    return True
                elif free_length > length:
                    # 如果大于,则分配出去并修改
                    cls.insert_allocated_table(start, length, name)
                    cls.free_table_list[i].start += length
                    cls.free_table_list[i].length -= length
                    return True

        print('内存不足,内存分配失败!!!')
        return False

    @classmethod
    def worst_fit(cls, length, name):
        """
        根据最坏适应算法,选取最大的内存区为作业分配内存,返回ture或false
        :param length:作业长度
        :param name:作业名称
        :return: True False
        """
        # 由于内存回收后是按照地址大小排序,因此重新对列表根据内存大小倒序排序
        cmpfun = operator.attrgetter('length')
        cls.free_table_list.sort(key=cmpfun, reverse=True)

        for i in range(len(cls.free_table_list)):
            start = cls.free_table_list[i].start
            free_length = cls.free_table_list[i].length
            if free_length >= length:
                if free_length == length:
                    # 如果内存大小刚好等于作业内存大小,插入已分配表,直接移除这一个空闲列表项
                    cls.insert_allocated_table(start, length, name)
                    cls.free_table_list.pop(i)
                    cls.free_table_list.sort(key=cmpfun, reverse=True)
                    return True
                elif free_length > length:
                    # 如果大于,则分配出去并修改
                    cls.insert_allocated_table(start, length, name)
                    cls.free_table_list[i].start += length
                    cls.free_table_list[i].length -= length
                    cls.free_table_list.sort(key=cmpfun, reverse=True)
                    return True

        print('内存不足,内存分配失败!!!')
        return False


class QuickZone:
    def __init__(self, start,length):
        self.allocated_table_list = []  # 已分配区列表
        # 空闲区列表,列表里面再嵌套一个列表,用于存放2的幂次方的空闲区的起止,大小
        self.free_area = []
        # 初始化空闲区列表
        self.max = int(numpy.log2(length))
        for power in range(self.max):
            if power != self.max - 1:
                # 放入空列表,表示没有划分2**i大小的分区
                self.free_area.append([])
            else:
                # 放入一个2**max大小的分区,如果一开始length=1024,幂次为10,那么没有经过分区,就直接在free_area[9]放入[t,]
                t = FreeAreaTable(start, length)
                self.free_area.append([t, ])

    def print_free_area(self):
        """
        打印free_area[]
        :return:
        """
        for i in range(len(self.free_area)):
            if self.free_area[i]:
                for j in self.free_area[i]:
                    print('2的次幂:', i + 1, 'start:', j.start, 'length:', j.length)
            else:
                print('2的次幂:', i + 1, self.free_area[i])

    def print_allocated_table_list(self):
        for i in self.allocated_table_list:
            print('作业名称:', i.name, '起址:', i.start, '作业长度', i.length, '分配内存大小:', i.mem_length)

    def divide_memory(self, power):
        """
        根据power对半分割出合适的内存
        :param power:log2向上取整的结果,内存大小的2次幂
        :return: 分割后self.free_area[]的下标
        """

        if power > self.max:
            return -1
        if power!=0:
            i = power - 1
        else:
            i=power
        # 如果刚好有2**power大小的内存,直接返回下标
        if self.free_area[i]:
            return i
        try:
            while self.free_area[i] == [] and i <= self.max:
                i += 1
        except:
            print('内存不足,无法分配')
            return -1
        start = self.free_area[i][0].start
        self.free_area[i].pop(0)
        t1 = FreeAreaTable(start, 2 ** i)
        t2 = FreeAreaTable(start + 2 ** i, 2 ** i)
        i -= 1
        self.free_area[i].append(t1)
        self.free_area[i].append(t2)
        if not self.free_area[power - 1]:
            return self.divide_memory(power)
        else:
            return i

    def quick_fit(self, length, name):
        """
        根据长度,用快速适应分配算法分配内存
        :param length: 作业长度
        :param name: 作业名称
        :return: True 或 False
        """
        # 求log2,并向上取整
        power = math.ceil(numpy.log2(length))
        mem_index = self.divide_memory(power)
        if mem_index == -1:
            return False
        t = self.free_area[mem_index].pop(0)
        t1 = AllocatedTable(start=t.start, length=length, name=name, mem_length=t.length)
        self.allocated_table_list.append(t1)
        return True

    def recovered_memory(self, start, length):
        """
        回收内存,并合并伙伴块
        :param start:起址
        :param length:内存长度
        :return:True or False
        """
        power = int(numpy.log2(length))
        index = power - 1
        state = 0
        # 移除已分配表
        for i in range(len(self.allocated_table_list)):
            if self.allocated_table_list[i].start == start:
                self.allocated_table_list.pop(i)
                state = 1
                break
        if state == 0:
            return False
        # 回收内存,合并
        t = FreeAreaTable(start, length)
        self.free_area[index].append(t)
        # 从下往上合并伙伴块
        for i in range(index, self.max):  # 遍历2的不同次幂
            # 排序
            cmpfun = operator.attrgetter('start')
            self.free_area[i].sort(key=cmpfun)
            for j in range(len(self.free_area[i])):  # 遍历同次幂的列表
                if j + 1 < len(self.free_area[i]):
                    if self.free_area[i][j].start + 2 ** (i + 1) == self.free_area[i][j + 1].start:
                        min_start = self.free_area[i][j].start
                        max_length = 2 ** (i + 2)
                        # 去除小的内存块
                        self.free_area[i].pop(j)
                        self.free_area[i].pop(j)
                        # 合并到大一级的内存块中
                        t = FreeAreaTable(min_start, max_length)
                        self.free_area[i + 1].append(t)
        return True
    def recovered_memory(self,name):
        """
        回收内存,并合并伙伴块
        :param name:作业名称
        :return:True or False
        """

        for i in self.allocated_table_list:
            if i.name==name:
                start=i.start
                length=i.mem_length
        power = int(numpy.log2(length))
        index = power - 1
        state = 0
        # 移除已分配表
        for i in range(len(self.allocated_table_list)):
            if self.allocated_table_list[i].start == start:
                self.allocated_table_list.pop(i)
                state = 1
                break
        if state == 0:
            return False
        # 回收内存,合并
        t = FreeAreaTable(start, length)
        self.free_area[index].append(t)
        # 从下往上合并伙伴块
        for i in range(index, self.max):  # 遍历2的不同次幂
            # 排序
            cmpfun = operator.attrgetter('start')
            self.free_area[i].sort(key=cmpfun)
            for j in range(len(self.free_area[i])):  # 遍历同次幂的列表
                if j + 1 < len(self.free_area[i]):
                    if self.free_area[i][j].start + 2 ** (i + 1) == self.free_area[i][j + 1].start:
                        min_start = self.free_area[i][j].start
                        max_length = 2 ** (i + 2)
                        # 去除小的内存块
                        self.free_area[i].pop(j)
                        self.free_area[i].pop(j)
                        # 合并到大一级的内存块中
                        t = FreeAreaTable(min_start, max_length)
                        self.free_area[i + 1].append(t)
        return True
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值