资源描述
操作系统 实验报告
实验名称:
操作系统的存储管理方式
班 级:
姓 名:
学 号:
类 型:
实验地点:
日 期:
一、实验目的:
1. 动态测试WINDOWS2000/XP系统内存
二、实验环境:
1. PC机一台(VC、C、VB等编程环境)
三、实验内容和要求:
1.了解WINDOWS 用户进程地址空间分布、系统地址空间分布、WINDOWS中用户空间内存分配方式(以页为单位的虚拟内存分配方法)、WINDOWS的内存保护机制。
四、实验步骤:
#include<iostream>
#include<cstring>
#include<ctime>
#include<windows.h>
using namespace std;
const int MM_SIZE=100; //内存块数
const int ROW=10; //绘制内存行数
const int COL=10; //绘制内存列数
const int NEME_LEN=10; //名字长度
const int WAITTIME=2000; //等待时间
int UsedNum=0; //当前已占用的内存块数
int FreeNum=MM_SIZE; //当前空闲的内存块数
int ProCnt=0; //当前用户进程数
int NowID=1; //当前分配的进程编号
int MM[MM_SIZE]; //Main Memony
//0 -> 内存块未被使用
//-1 -> 内存块在初始化时已被系统占用
//k -> 内存块已被分配给pID=k 的用户进程
/*进程Obj*/
class PROCESS
{
public:
PROCESS():next(0){} //构造函数重载,用于构造队列队头
PROCESS(char* Name,int pN):PageNum(pN),next(0)
{
pName=new char[NEME_LEN];
strcpy(pName,Name);
PageTable=new int[MM_SIZE];
for(int i=0;i<MM_SIZE;i++)
PageTable[i]=-1;
pID=NowID++;
}
~PROCESS()
{
delete pName;
delete PageTable;
}
PROCESS* next; //指向下一个进程
char* GetpName(void)const {return pName;} //获取进程名
int GetpID(void)const {return pID;} //获取进程编号
int GetPageNum(void)const {return PageNum;} //获取进程所需页数
void UnionTable(int i,int j); //关联页号i 与块号j(创建页表)
void PrintPageTable(void); //打印页表
protected:
char* pName; //进程名
int pID; //进程编号
int PageNum; //进程所需页数
int* PageTable; //页表
};
PROCESS* ProLinkHead=new PROCESS; //申请进程队列队头空间
void PROCESS::UnionTable(int i,int j)
{
PageTable[i]=j;
return;
}
void PROCESS::PrintPageTable(void)
{
cout<<" PAGETABLE (页表)"<<endl;
cout<<" 页号ID 块号ID#"<<endl;
for(int i=0;i<MM_SIZE;i++)
if(PageTable[i]!=-1)
printf(" %-2d %-2d\n",i,PageTable[i]);
cout<<endl;
return;
}
void Initial_MM(void); //初始化
void Menu(void); //菜单
void CheckMM(void); //查看内存状态
void PrintProList(void); //打印当前用户进程列表
void CheckPro(void); //查看进程状态
void CreatePro(void); //创建新用户进程
void DelPro(void); //删除用户进程
/*主函数*/
int main(void)
{
srand(time(0));
Initial_MM();
Menu();
return 0;
}
/*初始化内存状态*/
void Initial_MM(void)
{
memset(MM,0,sizeof(int)*MM_SIZE); //缺省所有内存块空闲(0)
int USE=rand()%4+2; //初始内存占用系数
int UsedMM=MM_SIZE/USE; //初始内存占用数 (占用率=USEMM/MM_SIZE)
for(int i=0;i<UsedMM;i++) //随机分配UsedMM 个内存块给系统(-1)
{
int id;
do
{
id=rand()%MM_SIZE;
}while(MM[id]==-1); //检查编号为id 的内存块是否已分配给系统
MM[id]=-1;
}
UsedNum+=UsedMM;
FreeNum-=UsedMM;
return;
}
/*菜单*/
void Menu(void)
{
int select;
while(true)
{
system("cls");
cout<<endl;
cout<<endl;
cout<<" 1. 检查内存的状态"<<endl;
cout<<endl;
cout<<" 2. 检查进程的状态"<<endl;
cout<<endl;
cout<<" 3. 创建新进程"<<endl;
cout<<endl;
cout<<" 4. 删除进程"<<endl;
cout<<endl;
cout<<" 5.退出"<<endl;
cout<<endl;
cout<<endl;
cin>>select;
if(select==5)
break;
switch(select)
{
case 1:CheckMM();break;
case 2:CheckPro();break;
case 3:CreatePro();break;
case 4:DelPro();break;
default:
{
cout<<"出现错误,请重新输入!!"<<endl;
Sleep(WAITTIME/2);
break;
}
}
}
return;
}
/*查看内存状态*/
void CheckMM(void)
{
system("cls");
cout<<endl;
cout<<" 主内存 (块号)ID#="<<ROW<<"*iR+jC"<<endl;
cout<<" 0C 1C 2C 3C 4C 5C 6C 7C 8C 9C"<<endl;
for(int i=0;i<ROW;i++)
{
printf("%dR ",i);
for(int j=0;j<COL;j++)
printf("%2d ",MM[ROW*i+j]);
cout<<endl;
}
cout<<" -1 : 系统使用的内存"<<endl;
cout<<" 0 : 释放内存"<<endl;
cout<<" n : PROCESS_n使用内存"<<endl;
cout<<endl;
cout<<"返回菜单? (Y/N)"<<endl;
while(true)
{
char Key;
cin>>Key;
if(Key=='Y' || Key=='y')
break;
cout<<"请输入 'Y'..."<<endl;
cout<<"你现在只能返回菜单"<<endl;
}
return;
}
/*创建新用户进程*/
void CreatePro(void)
{
system("cls");
cout<<endl;
cout<<" 创建新的进程"<<endl;
/*输入新进程参数*/
char name[NEME_LEN]; //新进程名字
int pN; //新进程所需占用的页数
cout<<" 新进程名字: ";
cin>>name;
cout<<" 新进程页数: ";
cin>>pN;
if(pN>FreeNum) //检查空闲块数是否足够分配给新进程
{
cout<<endl;
cout<<"内存不足! 无法创建该进程,请清理内存再重试"<<endl;
cout<<"自动返回菜单"<<endl;
Sleep(WAITTIME);
return;
}
else
{
ProCnt++;
UsedNum+=pN;
FreeNum-=pN;
}
/*创建新进程并插入进程队列*/
PROCESS* NewPro=new PROCESS(name,pN); //创建新进程对象并申请空间
PROCESS* tmp=NewPro; //把新进程插入进程队列
tmp->next=ProLinkHead->next;
ProLinkHead->next=tmp;
/*为进程分配内存*/
int j=0;
for(int i=0;i<pN;i++) //枚举进程页号,为其分配内存块
{
for(;j<MM_SIZE;j++) //枚举空闲的内存块号
if(MM[j]==0)
{
MM[j]=tmp->GetpID();
tmp->UnionTable(i,j);
break;
}
}
cout<<endl;
cout<<"创建进程 "<<name<<" 成功!"<<endl;
cout<<"自动返回菜单"<<endl;
Sleep(WAITTIME);
return;
}
/*打印当前用户进程列表*/
void PrintProList(void)
{
cout<<endl;
cout<<" 进程状态"<<endl;
cout<<"PID PAGENUM名称"<<endl;
PROCESS* p=ProLinkHead;
while(p->next)
{
p=p->next;
printf(" %-10s %2d %4d\n",p->GetpName(),p->GetpID(),p->GetPageNum());
}
return;
}
/*查看进程状态*/
void CheckPro(void)
{
system("cls");
PrintProList();
if(ProCnt==0)
{
cout<<"当前不存在任何用户进程"<<endl;
cout<<"自动返回菜单"<<endl;
Sleep(WAITTIME);
return;
}
cout<<"输入PID 查看指定进程的详细信息: "<<endl;
int pid;
cin>>pid;
bool flag=false; //标记是否找到编号为pid 的进程
PROCESS* p=ProLinkHead->next;
while(p)
{
if(p->GetpID()!=pid)
p=p->next;
else
{
flag=true;
break;
}
}
if(!flag)
cout<<"输入错误! 不存在的进程!"<<endl;
else
{
system("cls");
cout<<endl;
cout<<" PROCESS_"<<p->GetpName()<<'_'<<p->GetpID()<<endl;
cout<<" PAGENUM(页数) : "<<p->GetPageNum()<<endl;
cout<<endl;
p->PrintPageTable(); //打印pid 进程的页表
}
cout<<"Back to Menu? (Y/N)"<<endl;
while(true)
{
char Key;
cin>>Key;
if(Key=='Y' || Key=='y')
break;
cout<<"请输入 'Y'"<<endl;
cout<<"你现在只能返回菜单"<<endl;
}
return;
}
/*删除用户进程*/
void DelPro(void)
{
system("cls");
PrintProList(); //先打印用户进程列表
int select;
cout<<" (1) 删除指定进程."<<endl;
cout<<" (2) 删除所有进程."<<endl;
cout<<endl;
while(cin>>select)
{
if(select==1 || select==2)
break;
cout<<"错误!"<<endl;
}
cout<<endl;
if(select==1) //删除指定用户进程
{
int pid;
cout<<"输入页号 : ";
cin>>pid;
bool flag=false; //标记是否找到编号为pid 的进程
PROCESS* p1=ProLinkHead;
PROCESS* p2=ProLinkHead->next;
while(p2)
{
if(p2->GetpID()!=pid)
{
p1=p1->next;
p2=p2->next;
}
else
{
flag=true;
p1->next=p2->next;
delete p2; //释放pid 进程对象占用的空间
break;
}
}
if(flag)
{
ProCnt--;
for(int i=0;i<MM_SIZE;i++) //释放被pid 进程占用的内存块
if(MM[i]==pid)
{
MM[i]=0;
UsedNum--;
FreeNum++;
}
cout<<"删除成功!"<<endl;
}
else
cout<<"删除失败! 编号为PID 的进程不存在!"<<endl;
}
else //删除所有用户进程
{
NowID=1;
ProCnt=0;
PROCESS* p=ProLinkHead->next;
while(p)
{
PROCESS* tmp=p;
p=p->next;
delete tmp;
}
ProLinkHead->next=0;
for(int i=0;i<MM_SIZE;i++) //释放所有被用户进程占用的内存块
if(MM[i]>0)
{
MM[i]=0;
UsedNum--;
FreeNum++;
}
cout<<"所有进程删除成功!"<<endl;
}
cout<<"自动返回菜单"<<endl;
Sleep(WAITTIME);
return;
}
分别输入下列序号得到以下结果:
输入 Y
五、 实验结果与分析(含程序、数据记录及分析和实验总结等):
通过本次上机实践,使我了解了有关于存储管理的一些知识。存储管理必须为用户分配一个物理上的主存空间,为了避免主存中的各程序相互干扰还必须实现储存保护,为了有效的利用主存空间允许多个作业共享程序和数据,各储存管理方式实现这些功能的方法是不同的,并且都要有相应的硬件作支撑。
10 / 10
展开阅读全文