在学习操作系统时,讲到CPU对内存的寻址,会涉及到内存的管理方式,内存管理方式有如下四种: 1.单连续分区存储管理 2.页式存储管理 3.段式存储管理 4.段页式存储管理 其中,单连续分区存储管理可以分为1.固定分区存储管理和2.可变分区存储管理。 其中最复杂的是可变分区存储管理,内存管理效果最好,但是实际应用最多的是段页式存储管理。段页式存储管理实现考虑情况较少,实现起来相对简单,但是效率也很高。但是如果明白了可变分区存储管理,应该其他内存管理方式也明白了。
单连续分区存储管理
思想
维护两个数据结构: 1.用于存放空闲分区的双向链表 2.是用于存放内存中作业信息的线性表 将内存看成是一个大的块,当有作业申请内存时,就找第一个足够大小的空闲分区,将作业放入该分区,同时更新线性表和链表。如果没有足够大小的空间,就启动主存紧凑(将所有的主存外零头汇聚到高地址处),得到一个大的空闲分区块,然后判断是否满足分配条件。
算法实现
分配内存
只考虑三种情况 |1.作业C不能放入空闲分区。 |2.作业C可以放入空闲分区 ___|2.1剩下的内存大小不足以形成内存碎片,直接分配给该作业。 ___|2.2.作业C可以放入空闲分区,剩下的内存大小也足以形成内存碎片
void addTable(int name, int size,int addr) {
for (int i = 0; i < 100; i++) {
if (tab[i].flag == false) {
tab[i].name = name;
tab[i].addr = addr;
tab[i].length = size;
tab[i].flag = true;
return;
}
}
}
void alterTable() {
std::sort(tab, tab + 100, cmp);
tab[0].addr = 0;
for (int i = 1; i < 100; i++) {
if (!tab[i].flag) break;
tab[i].addr = tab[i - 1].addr + tab[i - 1].length;
}
}
void compactMem(pFreePartition p) {
if (p == NULL) {
return;
}
if (p->next == NULL) {
head = p;
p->back = NULL;
return;
}
p->next->size += p->size;
p->next->address -= p->size;
compactMem(p->next);
free(p);
}
void ffcolection() {
int size;
int name;
bool flag = false;
printf("\n----------模拟分配作业内存模块----------\n\n");
printf("\n请输入需要分配的作业名:\n");
scanf("%d", &name);
printf("\n请输入需要分配的内存大小(单位 B):\n");
scanf("%d", &size);
pFreePartition p = head;
while (p != NULL) {
if (p->size > size) {
if (p->size - size > MIN) {
addTable(name, size, p->address);
p->size = p->size - size;
p->address += size;
}
else {
addTable(name, p->size, p->address);
flag = true;
if (p == head) {
head = p->next;
free(p);
p = NULL;
}
else {
p->back->next = p->next;
free(p);
p = NULL;
}
}
break;
}
p = p->next;
}
if (p == NULL && flag == false) {
compactMem(head);
alterTable();
if (head==NULL||head->size < size) {
printf("无法为任务提供足够内存!!\n");
}
else {
addTable(name, size, head->address);
head->size -= size;
head->address += size;
if (head->size == 0) {
free(head);
head = NULL;
}
}
}
}
释放内存
四种情况: 情况一: 情况2: 情况3: 情况4: 实际上四种情况可以当成两种情况处理,先将空闲内存块插入,最后再进行空闲块整合。
void recolection() {
int name;
int address = -1;
int length;
printf("\n----------模拟释放内存模块----------\n\n");
printf("\n请输入要释放的作业名:\n\n");
scanf("%d", &name);
for (int i = 0; i < 100; i++) {
if (name == tab[i].name) {
address = tab[i].addr;
length = tab[i].length;
tab[i].flag = false;
tab[i].addr = INF;
}
}
if (address == -1) {
printf("任务名不存在!!\n");
return;
}
pFreePartition p = head;
pFreePartition pre = head;
while (p != NULL) {
if (p->address > address) {
break;
}
pre = p;
p = p->next;
}
if (p == NULL) {
p = (pFreePartition)malloc(sizeof(freePartition));
p->address = address;
p->next = NULL;
p->back = pre;
p->size = length;
if (p->back != NULL) {
p->back->next = p;
}
else {
head = p;
}
}
else {
pFreePartition temp = (pFreePartition)malloc(sizeof(freePartition));
temp->next = p;
temp->back = p->back;
p->back = temp;
if (temp->back != NULL) {
temp->back->next = temp;
}
else {
head = temp;
}
temp->address = address;
temp->size = length;
}
p = head->next;
while (p!=NULL&&p->back!=NULL) {
if (p->back->address + p->back->size == p->address) {
pFreePartition temp = p->back;
p->size += p->back->size;
p->address = p->back->address;
head = p;
free(temp);
}
p = p->next;
}
printf("内存释放完成\n");
}
查看内存使用情况和作业管理表使用情况
void seeSimulateMemory() {
printf("\n空闲分区使用情况:\n\n");
pFreePartition p = head;
while (p != NULL) {
printf("address:%d size:%d\n", p->address,p->size);
p = p->next;
}
printf("\n-----------任务分配情况----------\n\n");
for (int i = 0; i < 100; i++) {
if (tab[i].flag==true) {
printf("name:%d address:%d length:%d\n", tab[i].name, tab[i].addr, tab[i].length);
}
}
printf("空闲分区查看完成");
}
完整代码
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<algorithm>
#define debug(x) printf("debug:%s",x);
#define freep NULL;
const int INF = 0x3f3f3f3f;
const int MIN = 5;
typedef unsigned int Uint;
typedef struct node {
Uint size;
struct node* next;
struct node* back;
Uint address;
}freePartition,*pFreePartition;
typedef struct table {
int name;
Uint length;
int addr;
bool flag;
}memTable;
pFreePartition head;
memTable tab[100];
void init() {
int size;
head = (pFreePartition)malloc(sizeof(freePartition));
printf("请输入总分区大小:");
scanf("%d", &size);
assert(size > 5);
head->next = freep;
head->address = 0;
head->back = freep;
head->size = size;
for (int i = 0; i < 100; i++) {
tab[i].addr = INF;
tab[i].flag = false;
}
return ;
}
void addTable(int name, int size,int addr) {
for (int i = 0; i < 100; i++) {
if (tab[i].flag == false) {
tab[i].name = name;
tab[i].addr = addr;
tab[i].length = size;
tab[i].flag = true;
return;
}
}
}
bool cmp(memTable a, memTable b) {
return a.addr < b.addr;
}
void alterTable() {
std::sort(tab, tab + 100, cmp);
tab[0].addr = 0;
for (int i = 1; i < 100; i++) {
if (!tab[i].flag) break;
tab[i].addr = tab[i - 1].addr + tab[i - 1].length;
}
}
void compactMem(pFreePartition p) {
if (p == NULL) {
return;
}
if (p->next == NULL) {
head = p;
p->back = NULL;
return;
}
p->next->size += p->size;
p->next->address -= p->size;
compactMem(p->next);
free(p);
}
void ffcolection() {
int size;
int name;
bool flag = false;
printf("\n----------模拟分配作业内存模块----------\n\n");
printf("\n请输入需要分配的作业名:\n");
scanf("%d", &name);
printf("\n请输入需要分配的内存大小(单位 B):\n");
scanf("%d", &size);
pFreePartition p = head;
while (p != NULL) {
if (p->size > size) {
if (p->size - size > MIN) {
addTable(name, size, p->address);
p->size = p->size - size;
p->address += size;
}
else {
addTable(name, p->size, p->address);
flag = true;
if (p == head) {
head = p->next;
free(p);
p = NULL;
}
else {
p->back->next = p->next;
free(p);
p = NULL;
}
}
break;
}
p = p->next;
}
if (p == NULL && flag == false) {
compactMem(head);
alterTable();
if (head==NULL||head->size < size) {
printf("无法为任务提供足够内存!!\n");
}
else {
addTable(name, size, head->address);
head->size -= size;
head->address += size;
if (head->size == 0) {
free(head);
head = NULL;
}
}
}
}
void recolection() {
int name;
int address = -1;
int length;
printf("\n----------模拟释放内存模块----------\n\n");
printf("\n请输入要释放的作业名:\n\n");
scanf("%d", &name);
for (int i = 0; i < 100; i++) {
if (name == tab[i].name) {
address = tab[i].addr;
length = tab[i].length;
tab[i].flag = false;
tab[i].addr = INF;
}
}
if (address == -1) {
printf("任务名不存在!!\n");
return;
}
pFreePartition p = head;
pFreePartition pre = head;
while (p != NULL) {
if (p->address > address) {
break;
}
pre = p;
p = p->next;
}
if (p == NULL) {
p = (pFreePartition)malloc(sizeof(freePartition));
p->address = address;
p->next = NULL;
p->back = pre;
p->size = length;
if (p->back != NULL) {
p->back->next = p;
}
else {
head = p;
}
}
else {
pFreePartition temp = (pFreePartition)malloc(sizeof(freePartition));
temp->next = p;
temp->back = p->back;
p->back = temp;
if (temp->back != NULL) {
temp->back->next = temp;
}
else {
head = temp;
}
temp->address = address;
temp->size = length;
}
p = head->next;
while (p!=NULL&&p->back!=NULL) {
if (p->back->address + p->back->size == p->address) {
pFreePartition temp = p->back;
p->size += p->back->size;
p->address = p->back->address;
head = p;
free(temp);
}
p = p->next;
}
printf("内存释放完成\n");
}
void recolectionALL() {
int size = 0;
printf("\n释放链表的的所有内存\n\n");
pFreePartition p = head;
while (p != NULL) {
pFreePartition temp = p;
p = p->next;
size += p->size;
free(temp);
}
for (int i = 0; i < 100; i++) {
if (tab[i].flag) {
size += tab[i].length;
}
}
p = (pFreePartition)malloc(sizeof(freePartition));
p->back = NULL;
p->next = NULL;
p->address = 0;
p->size = size;
printf("内存释放完成");
}
void seeSimulateMemory() {
printf("\n空闲分区使用情况:\n\n");
pFreePartition p = head;
while (p != NULL) {
printf("address:%d size:%d\n", p->address,p->size);
p = p->next;
}
printf("\n-----------任务分配情况----------\n\n");
for (int i = 0; i < 100; i++) {
if (tab[i].flag==true) {
printf("name:%d address:%d length:%d\n", tab[i].name, tab[i].addr, tab[i].length);
}
}
printf("空闲分区查看完成");
}
void menu() {
int key;
init();
while (1) {
printf("------------------模拟命令菜单------------------\n\n");
printf("---------------模拟分配内存 键入1--------------\n\n");
printf("---------------模拟释放内存 键入2--------------\n\n");
printf("-------------模拟释放所有内存 键入3--------------\n\n");
printf("----------------退出系统 键入0----------------\n\n");
printf("目前内存使用情况如下:\n");
seeSimulateMemory();
printf("请输入命令:");
scanf("%d", &key);
switch (key) {
case 1:
ffcolection();
break;
case 2:
recolection();
break;
case 3:
recolectionALL();
break;
case 0:
recolectionALL();
exit(0);
default:
printf("\n命令不存在,请重新输入\n\n");
}
}
}
|