按书上的,算法有五种,最先适应、最佳适应、最坏适应、下次适应、快速适应(或者说是伙伴算法,其实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