#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TOTAL_MEMORY 640
// 定义分区节点结构
typedef struct SubArea {
char name[20]; // 作业名称 (空闲区通常叫 "Free")
int start; // 起始地址
int length; // 分区长度
struct SubArea *next; // 指向下一个分区的指针
} SubArea;
// 定义两个链表的头指针
SubArea *free_head = NULL; // 空闲分区表
SubArea *allocated_head = NULL; // 已分配分区表
// --- 辅助函数:初始化 ---
void init() {
free_head
= (SubArea
*)malloc(sizeof(SubArea
)); strcpy(free_head
->name
, "Free"); free_head->start = 0;
free_head->length = TOTAL_MEMORY;
free_head->next = NULL;
allocated_head = NULL; // 初始没有作业
}
// --- 辅助函数:显示当前内存状况 ---
void print_memory() {
SubArea *p;
printf("\n-------------------------------------------------------\n"); printf("| %-15s | %-10s | %-10s |\n", "Partition Type", "Start Addr", "Length (KB)"); printf("-------------------------------------------------------\n");
// 打印已分配分区
p = allocated_head;
while (p != NULL) {
printf("| Used (%-8s) | %-10d | %-10d |\n", p
->name
, p
->start
, p
->length
); p = p->next;
}
// 打印空闲分区
p = free_head;
while (p != NULL) {
printf("| Free | %-10d | %-10d |\n", p
->start
, p
->length
); p = p->next;
}
printf("-------------------------------------------------------\n"); }
// --- 核心逻辑:分配内存 ---
// alg_type: 1=First Fit, 2=Best Fit, 3=Worst Fit
void allocate(char *job_name, int request_size, int alg_type) {
SubArea *p = free_head;
SubArea *prev = NULL; // 遍历时的前驱
SubArea *target = NULL; // 选中的空闲块
SubArea *target_prev = NULL; // 选中的空闲块的前驱
// 根据算法查找合适的空闲块
if (alg_type == 1) { // 首次适应算法 (First Fit)
while (p != NULL) {
if (p->length >= request_size) {
target = p;
target_prev = prev;
break; // 找到第一个就停止
}
prev = p;
p = p->next;
}
}
else if (alg_type == 2) { // 最佳适应算法 (Best Fit)
int min_diff = TOTAL_MEMORY + 1; // 设置一个最大值
while (p != NULL) {
if (p->length >= request_size && (p->length - request_size < min_diff)) {
min_diff = p->length - request_size;
target = p;
target_prev = prev;
}
prev = p;
p = p->next;
}
}
else if (alg_type == 3) { // 最坏适应算法 (Worst Fit)
int max_diff = -1;
while (p != NULL) {
if (p->length >= request_size && (p->length - request_size > max_diff)) {
max_diff = p->length - request_size;
target = p;
target_prev = prev;
}
prev = p;
p = p->next;
}
}
// 开始分配
if (target == NULL) {
printf("\n[Fail] Memory allocation failed for %s (Size: %dKB). No suitable block.\n", job_name
, request_size
); return;
}
// 1. 创建新的已分配节点
SubArea
*new_alloc
= (SubArea
*)malloc(sizeof(SubArea
)); strcpy(new_alloc
->name
, job_name
); new_alloc->start = target->start;
new_alloc->length = request_size;
new_alloc->next = allocated_head; // 头插法插入已分配链表
allocated_head = new_alloc;
// 2. 更新空闲链表
if (target->length == request_size) {
// 如果大小正好相等,直接从空闲链表中删除该节点
if (target_prev == NULL) { // 是头节点
free_head = target->next;
} else {
target_prev->next = target->next;
}
} else {
// 如果有剩余空间,修改起始地址和长度
target->start += request_size;
target->length -= request_size;
}
printf("\n[Success] Allocated %dKB to %s.\n", request_size
, job_name
); }
// --- 核心逻辑:回收内存 ---
void reclaim(char *job_name) {
SubArea *p = allocated_head;
SubArea *prev = NULL;
// 1. 在已分配表中查找作业
while (p != NULL) {
if (strcmp(p
->name
, job_name
) == 0) break; prev = p;
p = p->next;
}
if (p == NULL) {
printf("\n[Error] Job %s not found in memory.\n", job_name
); return;
}
// 2. 从已分配表中移除
if (prev == NULL) allocated_head = p->next;
else prev->next = p->next;
int recover_start = p->start;
int recover_len = p->length;
free(p
); // 释放已分配节点结构,准备创建新的空闲节点
// 3. 插入空闲链表(按地址排序)
SubArea
*new_free
= (SubArea
*)malloc(sizeof(SubArea
)); strcpy(new_free
->name
, "Free"); new_free->start = recover_start;
new_free->length = recover_len;
// 寻找插入位置
SubArea *curr = free_head;
SubArea *pre_curr = NULL;
// 如果空闲表为空
if (free_head == NULL) {
free_head = new_free;
new_free->next = NULL;
} else {
// 找到第一个起始地址大于待插入块地址的节点
while (curr != NULL && curr->start < new_free->start) {
pre_curr = curr;
curr = curr->next;
}
// 插入逻辑
if (pre_curr == NULL) { // 插在头部
new_free->next = free_head;
free_head = new_free;
} else { // 插在中间或尾部
new_free->next = pre_curr->next;
pre_curr->next = new_free;
}
}
// 4. 合并空闲分区 (Coalescing)
// 检查是否可以与后一个合并
if (new_free->next != NULL && (new_free->start + new_free->length == new_free->next->start)) {
SubArea *temp = new_free->next;
new_free->length += temp->length;
new_free->next = temp->next;
}
// 检查是否可以与前一个合并 (pre_curr是前一个节点)
// 注意:这里需要判断 pre_curr 是否存在且正好与 new_free 相邻
if (pre_curr != NULL && (pre_curr->start + pre_curr->length == new_free->start)) {
pre_curr->length += new_free->length;
pre_curr->next = new_free->next;
}
printf("\n[Success] Reclaimed memory from %s.\n", job_name
); }
// --- 主菜单 ---
int main() {
int choice;
int alg;
char name[20];
int size;
init(); // 初始化内存
printf("Select Allocation Algorithm:\n"); printf("1. First Fit (FF)\n"); printf("3. Worst Fit (WF)\n");
while (1) {
print_memory();
printf("\n1. Allocate Job 2. Reclaim Job 0. Exit\n");
if (choice == 0) break;
if (choice == 1) {
printf("Enter Job Name (e.g., J1): "); allocate(name, size, alg);
}
else if (choice == 2) {
printf("Enter Job Name to Reclaim: "); reclaim(name);
}
}
return 0;
}