📅  最后修改于: 2023-12-03 14:50:08.386000             🧑  作者: Mango
本文介绍一种内存管理算法——最差适合算法,同时提供该算法的代码实现及相关解释。
最差适合算法是一种动态分配存储器的算法,在该算法中,当需要分配一段内存空间时,将遍历空闲链表,查找最差、最大的空闲区。如果未找到足够大的空闲区,则将会对内存进行合并,直到找到能够满足请求的空闲区为止。
当释放内存空间时,将通过合并相邻的空闲区来创建更大的空闲区,同时更新空闲链表。
下面是该算法的 C 代码实现,代码中包括注释以帮助理解。
#include <stdio.h>
#include <stdlib.h>
#define MAX_MEM_SIZE 10 // 内存大小为 10KB
// 进程控制块(PCB)
typedef struct pcb {
int pid; // 进程 ID
int memory_size; // 内存占用大小
struct pcb* next; // 链表指针
} PCB;
// 空闲链表结点
typedef struct free_node {
int start_addr; // 起始地址
int end_addr; // 结束地址
struct free_node* next; // 链表指针
} FREE_NODE;
PCB* pcb_list = NULL; // PCB 链表头指针
// 空闲链表头指针
FREE_NODE* free_list = NULL;
// 初始化空闲链表
void init_free_linklist() {
// 将整个内存作为一块空闲区域
FREE_NODE* free_block = (FREE_NODE*)malloc(sizeof(FREE_NODE));
free_block->start_addr = 0;
free_block->end_addr = MAX_MEM_SIZE*1024-1;
free_block->next = NULL;
free_list = free_block;
}
// 按进程的 ID 查找 PCB
PCB* find_pcb(int pid) {
PCB* p = pcb_list;
while(p != NULL) {
if(p->pid == pid)
return p;
p = p->next;
}
return NULL;
}
// 创建 PCB
PCB* create_pcb(int pid, int size) {
PCB* p = (PCB*)malloc(sizeof(PCB));
p->pid = pid;
p->memory_size = size;
p->next = NULL;
return p;
}
// 按起始地址查找空闲链表中的结点
FREE_NODE* find_free_node(int start_addr) {
FREE_NODE* p = free_list;
while(p != NULL) {
if(p->start_addr == start_addr)
return p;
p = p->next;
}
return NULL;
}
// 分配内存
int malloc_pcb(int pid, int size) {
if(size <= 0) // 非法赋值
return -1;
if(find_pcb(pid) != NULL) // PCB 已存在
return -2;
int start_addr = -1, end_addr = -1;
int max_avail_size = -1; // 最大可用内存
FREE_NODE* p = free_list;
FREE_NODE* max_avail_node = NULL;
while(p != NULL) { // 遍历空闲链表
int avail_size = p->end_addr-p->start_addr+1;
if(avail_size >= size && avail_size > max_avail_size) {
max_avail_node = p;
max_avail_size = avail_size;
}
p = p->next;
}
if(max_avail_node == NULL) // 没有足够的内存,分配失败
return -3;
start_addr = max_avail_node->start_addr;
end_addr = start_addr+size-1;
if(max_avail_node->start_addr == start_addr) { // 分配后,剩下的空闲区块(如果有)继续插入空闲链表
max_avail_node->start_addr = end_addr+1;
if(max_avail_node->start_addr > max_avail_node->end_addr) {
if(max_avail_node == free_list)
free_list = free_list->next;
else {
FREE_NODE* pre_node = free_list;
while(pre_node->next != max_avail_node)
pre_node = pre_node->next;
pre_node->next = max_avail_node->next;
}
free(max_avail_node);
}
} else if(max_avail_node->end_addr == end_addr) { // 同上,处理尾部
max_avail_node->end_addr = start_addr-1;
} else {
FREE_NODE* new_node = (FREE_NODE*)malloc(sizeof(FREE_NODE));
new_node->start_addr = end_addr+1;
new_node->end_addr = max_avail_node->end_addr;
new_node->next = max_avail_node->next;
max_avail_node->end_addr = start_addr-1;
max_avail_node->next = new_node;
}
// 创建 PCB
PCB* new_pcb = create_pcb(pid, size);
new_pcb->next = pcb_list;
pcb_list = new_pcb;
return 0;
}
// 释放内存
int free_pcb(int pid) {
PCB* p = find_pcb(pid);
if(p == NULL)
return -1;
FREE_NODE* free_block = (FREE_NODE*)malloc(sizeof(FREE_NODE));
free_block->start_addr = p->memory_size;
free_block->end_addr = p->memory_size+p->memory_size-1;
p->memory_size = 0;
if(pcb_list == p)
pcb_list = pcb_list->next;
else {
PCB* pre_pcb = pcb_list;
while(pre_pcb->next != p)
pre_pcb = pre_pcb->next;
pre_pcb->next = p->next;
}
// 释放内存
if(free_list == NULL) { // 空闲链表为空
free_block->next = NULL;
free_list = free_block;
} else {
FREE_NODE* pre_free_node = NULL;
FREE_NODE* cur_free_node = free_list;
while(cur_free_node != NULL && cur_free_node->start_addr <= free_block->start_addr) {
pre_free_node = cur_free_node;
cur_free_node = cur_free_node->next;
}
// 按块首地址升序插入空闲链表
if(pre_free_node == NULL) { // 更新头结点
if(free_block->end_addr+1 == free_list->start_addr) {
free_list->start_addr = free_block->start_addr;
free_block = free_list;
} else
free_block->next = free_list;
free_list = free_block;
} else if(pre_free_node->end_addr+1 == free_block->start_addr && cur_free_node != NULL && cur_free_node->start_addr == free_block->end_addr+1) { // 与两侧空闲块合并
pre_free_node->end_addr = cur_free_node->end_addr;
pre_free_node->next = cur_free_node->next;
free(cur_free_node);
if(free_block->start_addr == pre_free_node->end_addr+1) {
pre_free_node->end_addr = free_block->end_addr;
free(cur_free_node);
} else {
free_block->next = pre_free_node;
pre_free_node->next = cur_free_node;
}
free(free_block);
} else if(pre_free_node->end_addr+1 == free_block->start_addr) { // 与前面的空闲块合并
pre_free_node->end_addr = free_block->end_addr;
free_block->next = pre_free_node->next;
pre_free_node->next = free_block;
} else if(cur_free_node != NULL && cur_free_node->start_addr == free_block->end_addr+1) { // 与后面的空闲块合并
cur_free_node->start_addr = free_block->start_addr;
free_block->next = cur_free_node;
pre_free_node->next = free_block;
} else { // 插入到空闲链表中
free_block->next = cur_free_node;
pre_free_node->next = free_block;
}
}
return 0;
}
// 打印内存使用情况
void print_memory_status() {
FREE_NODE* p = free_list;
if(p == NULL) {
printf("内存已全部分配\n");
return;
}
printf("空闲内存:\n");
while(p != NULL) {
printf("起始地址:%d,结束地址:%d,空闲大小:%dKB\n", p->start_addr, p->end_addr, (p->end_addr-p->start_addr+1)/1024);
p = p->next;
}
printf("已分配内存:\n");
PCB* q = pcb_list;
while(q != NULL) {
printf("进程 ID:%d,占用内存大小:%dKB\n", q->pid, q->memory_size/1024);
q = q->next;
}
}
int main() {
init_free_linklist(); // 初始化空闲链表
malloc_pcb(1, 2048); // 为进程 1 分配 2KB 的内存
malloc_pcb(2, 4096); // 为进程 2 分配 4KB 的内存
malloc_pcb(3, 8192); // 为进程 3 分配 8KB 的内存
free_pcb(2); // 释放进程 2 的内存
print_memory_status(); // 打印内存使用情况
return 0;
}
最差适合算法在内存管理中广泛应用,因为它能够及时释放不再使用的内存,从而使可用内存更加充足,提高系统的效率。该算法对于内存的释放和分配十分灵活,但同时也存在一定的缺陷,比如容易出现内存碎片等问题。因此,在实际使用中,需要根据具体情况进行选择和改进,以达到最优的内存管理效果。