1、实验内容
内存空间的初始化——可以由用户输入初始内存空间各个物理块情况。(用二维矩阵的
方式按物理块号,逐行给出每个物理块的状态,1——表示已分配,0——表示未分配,并
能够将行标、列标转换为对应的物理块号,以查看或修改每一个块的状态,要求:初始时部
分物理块已分配)
基本分页的分配过程:由用户输入作业号和作业的大小(这里的大小是逻辑页面数),
实现分配过程:空间充足,分配,修改状态矩阵的相应位置的值(值由 0 转变为 1),并用
专门的数据结构记录下该作业占用的物理块的块号,以备删除作业时回收空间。
作业空间的回收:用户输入作业号,实现分区回收(通过相应的数据结构找到该作业占
有的物理块号,将块号转变成对应的行标、列标,将对应位置的值由 1 转变成 0 就完成了
回收)。
分区的显示:任何时刻,可以查看当前内存的情况(显示记录内存情况的矩阵的值)。
2、实验要求
(1)内存空间不足的情况,要有相应的显示;
(2)作业不能同名,但是删除后可以再用这个名字;
(3)作业空间回收是输入作业名,回收相应的空间,如果这个作业名不存在,也要有
相应的提示。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bits/stdc++.h>
typedef struct Ln
{
int f; //作业号
int n; //作业页数
int len; //作业大小
char name[8]; //作业名
int y[100]; //页表,下标表示页号,内容表示作业各页所在物理块
struct Ln *next;
} Ln, *List;
int S[100]; //内存物理块,0:未使用,非0:已使用
int max = 99; //记录内存的物理块数,值为A[100]最大下标
int num = 100; //记录内存未使用物理块数
void Create_Pagi(); //建立分页作业
void Revoke_Pagi(); //回收作业
void Look_Pagi(); //显示所有作业占用的物理块
void Show_Pagi(); // 查看作业
void Pagi(); //分页界面
void Create_Segm(); //创建分段作业
void Show_Segm(); //显示作业信息
void Suggest(); //建议模块
void Dispatch(); //调用模块
void Segme(); //分段界面
void main_s(); //主界面
//建立新作业
void Create_Pagi(List &L)
{
int i, flag;
int m, k;
List p;
List n_node;
n_node = (List)malloc(sizeof(Ln));
p = L;
printf("请输入作业号 :");
scanf("%d", &n_node->f); //输入作业号
flag = 0; //三次输入错误返回上一层
while (p != NULL && flag < 3) // 查找作业号是否重复
{
if (p->f != n_node->f)
p = p->next;
else
{
printf("\n 该作业已存在您忘记了吗 , 请重新输入 :");
scanf("%d", &n_node->f);
p = L; //p 重新指向头结点
flag++;
}
}
if (flag < 3)
{
printf(" 输入作业名称 :");
scanf("%s", n_node->name);
printf(" 输入作业的大小 (单位为K):");
scanf("%d", &n_node->len); //例如1025,作业页数为1,但K不为0,所以+1=2;
n_node->n = n_node->len / 1024;
k = n_node->len % 1024;
if (k != 0)
n_node->n = n_node->n + 1;
printf(" 所需要的页数为 :");
printf("%d\n", n_node->n);
printf(" 偏移量为%d", k);
if (n_node->n > num) //放不进去,失败
{
printf("\n 对不起,内存物理块不足,新建作业失败 \n\n");
}
else
{
num -= n_node->n; //更新剩余物理块
m = 0;
for (i = 0; i <= max; i++)
if (S[i] == 0 && m < n_node->n) //
{
S[i] = n_node->f; //作业号
n_node->y[m] = i; //页表,下标表示页号,内容表示作业各页所在物理块
m++;
}
printf("\n");
printf(" 页号\t\t块号\n");
for (int i = 0; i < m; i++)
printf(" %d\t\t%d\n", i, n_node->y[i]);
int a, b;
while (1)
{
printf(" 请输入页号\n");
scanf("%d", &a);
printf(" 请输入页内偏移\n");
scanf("%d", &b);
if (a < m)
{
printf(" 物理地址:%d\n", n_node->y[a] * 1024 + b);
break;
}
else
{
printf(" 越界\n");
continue;
}
}
if (L == NULL)
L = n_node;
else
{
p = L; // 查找最后一个节点
while (p->next != NULL)
{
p = p->next;
}
p->next = n_node;
}
n_node->next = NULL;
}
}
else
{
printf("\n 操作错误次数过多 , 已为您返回主菜单 :");
}
}
//回收作业、释放内存
void Revoke_Pagi(List &L)
{
List p, q;
int x;
printf(" 请输入要删除的作业号 :");
scanf("%d", &x);
p = L; //查找作业;用 p 记录
q = p;
while (p != NULL)
{
if (p->f == x) //作业号
{
printf(" 该作业已为您删除 ");
break;
}
else
{
q = p;
p = p->next;
}
}
if (p == NULL) //p为空说明不存在此作业
{
printf("\n 该作业不存在\n");
}
else //对该作业进行删除
{
for (int i = 0; i < p->n; i++)
S[p->y[i]] = 0; //内存物理块
num += p->n;
if (p->f == q->f) //要删除的是头结点
{
L = p->next;
}
else
{
q->next = p->next;
}
}
}
// 显示所有作业占用的物理块
void Printf_Pagi(List L)
{
//int i = 0;
printf("\n 内存物理块分配情况 :\n");
List p = L;
printf(" 该作业信息 :\n");
printf(" 作业号 \t 作业名称 \t 作业页数 \t 所用物理块 \n");
while (p != NULL)
{
printf(" %d\t\t", p->f);
printf(" %s\t\t", p->name);
printf(" %d\t\t", p->n);
int i;
for (i = 0; i < p->n; i++)
printf(" %d", p->y[i]);
printf("\n");
p = p->next;
}
}
// 查看作业
void Look_Pagi(List L)
{
int z;
printf(" 请输入要查询的作业号: ");
scanf("%d", &z); //输入查看的作业号
List p = L;
while (p != NULL)
{
if (p->f == z) //相同直接输出
{
printf(" 作业号 \t 作业名称 \t 作业页数 \t 所用物理块 \n");
printf(" %d\t\t", p->f);
printf(" %s\t\t", p->name);
printf(" %d\t\t", p->n);
int i;
for (i = 0; i < p->n; i++)
printf(" #%d", p->y[i]);
printf("\n");
break;
}
else
p = p->next;
}
if (p == NULL)
printf(" 要查询的作业不存在 \n");
}
// 显示内存块使用情况,不分作业
void Show_Pagi()
{
printf(" 内存物理块分配情况 \n");
for (int i = 0; i <= max; i++)
{
printf(" %d\t", S[i]);
if (i % 10 == 9)
printf("\n");
}
}
//以上分页代码
/*------------------------------------------------------------------*/
//以下分段代码
using namespace std;
struct seg //定义结构体段seg
{
long cap; //该段的长度
long phy; //物理地址
long rea; //该段实际地址
};
struct Table //定义结构体段表Table
{
seg s[10]; //段表中每个段的属性
char name[50]; //段表名
int flag; //标记是否被调度内存
int num; //作业中包含段数
long total; //作业所占用的存储空间
};
Table Ts[10];
long mem = 0;
int Tnum = 0;
long k = 0;
long base = 0;
//创建分段作业
void Create_Segm()
{
printf("\n");
printf("请输入要创建的作业名:");
cin >> Ts[Tnum + 1].name;
printf("请输入该作业的段数:");
cin >> Ts[Tnum + 1].num;
int p = 0;
for (int i = 1; i <= Ts[Tnum + 1].num; i++)
{
printf("请输入该作业第%d段的大小:", i);
cin >> Ts[Tnum + 1].s[i].cap; //该作业每段的大小
Ts[Tnum + 1].s[i].phy = p; //物理地址赋值给p
p = p + Ts[Tnum + 1].s[i].cap; //每段的物理地址赋值给加和
}
printf("\n");
Ts[Tnum + 1].flag = 0; //标记是否被调度
Ts[Tnum + 1].total = p;
Tnum++;
}
//显示作业信息
void Show_Segm(int i)
{
printf("\n作业p%d:", i);
cout << "名字:" << Ts[i].name << endl;
cout << "该作业所占用的存储空间:" << Ts[i].total << endl;
if (Ts[i].flag == 0)
cout << "作业未调用" << endl;
else
cout << "作业已调用" << endl;
cout << "段 号 物理始址 内存始址 长度" << endl;
for (int j = 1; j <= Ts[i].num; j++)
{
cout << setw(3) << j << setw(11) << Ts[i].s[j].phy;
if (Ts[i].flag == 0)
cout << setw(11) << " ";
else
cout << setw(11) << Ts[i].s[j].rea;
cout << setw(11) << Ts[i].s[j].cap << endl;
}
}
//调用作业
void Dispatch()
{
cout << endl;
cout << "输入要调度的作业:p";
int n;
cin >> n;
if (n <= 0 || n > Tnum) //排除非正常可能
{
cout << "请求的段表不存在!" << endl;
cout << "请重新";
Dispatch(); //重新调度
}
else if (Ts[n].flag == 1) //已经标记
cout << "操作失败,该作业已经被调入到内存!" << endl;
else if (Ts[n].total > mem - k) //存储不足
cout << "内存空间不足,无法调度!" << endl;
else
{
for (int j = 1; j <= Ts[n].num; j++)
{
Ts[n].s[j].rea = Ts[n].s[j].phy + k; //
}
k = k + Ts[n].total;
Ts[n].flag = 1; //标记被访问
cout << "调度后的结果是:" << endl;
Show_Segm(n);
}
}
//建议模块
void Suggest()
{
printf(" 请输入您宝贵的建议:");
char s[10000];
scanf("%s", s);
printf(" *感谢您的宝贵建议,我们10分钟之内会受理您的建议* \n");
printf(" *感谢您的本次使用,退出程序请输入【0】,返回主界面输入【1】: ");
char m;
cin >> m;
do
if (m - '0' == 0)
exit(0);
else if (m - '1' == 1)
main_s();
else
{
printf(" 对不起,输入有误,默认返回主界面呢\n\n");
main_s();
}
while (m != 0);
}
//分页
void Pagi()
{
memset(S, 0, sizeof(S)); //初始化A
List L = NULL;
int i = 0;
do
{
printf("\t\t 欢迎使用基本分页存储管理系统 \n");
printf("\t\t******************************\n");
printf("\t\t* 1. 添加作业 *\n");
printf("\t\t* 2. 回收作业 *\n");
printf("\t\t* 3. 内存占用情况 *\n");
printf("\t\t* 4. 查看作业 *\n");
printf("\t\t* 5. 提出宝贵建议 *\n");
printf("\t\t* 6. 返回主界面 *\n");
printf("\t\t* 0. 退出程序 *\n");
printf("\t\t******************************\n");
printf(" 请输入您的选择 :");
scanf("%d", &i);
switch (i)
{
case 1:
Create_Pagi(L);
//Printf_Pagi(L);
break;
case 2:
Revoke_Pagi(L);
Printf_Pagi(L);
break;
case 3:
Show_Pagi();
break;
case 4:
Look_Pagi(L);
break;
case 5:
Suggest();
break;
case 6:
main_s();
break;
case 0:
printf(" 感谢您的使用,祝您生活愉快!");
exit(0);
}
} while (i != 0);
}
//分段
void Segme()
{
int i;
printf(" 请输入内存的大小:");
int m;
scanf("%d", &m);
do
{
printf("\t\t 欢迎使用基本分段存储管理系统 \n");
printf("\t\t******************************\n");
printf("\t\t* 1. 创建作业 *\n");
printf("\t\t* 2. 显示作业信息 *\n");
printf("\t\t* 3. 调度作业 *\n");
printf("\t\t* 4. 提出宝贵建议 *\n");
printf("\t\t* 5. 返回主界面 *\n");
printf("\t\t* 0. 退出程序 *\n");
printf("\t\t******************************\n");
printf(" 请输入您的选择 :");
scanf("%d", &i);
switch (i)
{
case 1:
Create_Segm();
break;
case 2:
for (int j = 1; j < Tnum + 1; j++)
Show_Segm(j);
break;
case 3:
if (i == 3) //如果输入是3则调度一个作业
Dispatch();
else
cout << " 输入错误!请重新输入!" << endl;
break;
case 4:
Suggest();
break;
case 5:
main_s();
break;
case 0:
printf(" 感谢您的使用,祝您生活愉快!");
exit(0);
}
} while (i != 0);
}
//主界面
void main_s()
{
printf("\t\t 欢迎来到内存管理系统 \n");
printf("\t\t**********************\n");
printf("\t\t* 1.进入分页管理系统 *\n");
printf("\t\t* 2.进入分段管理系统 *\n");
printf("\t\t* 3.我要提出宝贵建议 *\n");
printf("\t\t* 0.退出程序 *\n");
int m;
printf(" 请输入您的选择 :");
scanf("%d", &m);
do
if (m >= 0 && m <= 3)
{
switch (m)
{
case 1:
Pagi(); //分页
break;
case 2:
Segme(); //分段
break;
case 3:
Suggest();
break;
case 0:
exit(0);
}
}
else
{
printf(" 输入有误!请重新输入:");
scanf("%d", &m);
}
while (m != 0);
}
int main()
{
main_s();
return 0;
}