这个是操作系统的第二实验
二、分页式存储管理
●基本要求:在第1部分实验基础上实现进程的分页式内存分配和地址转换过程,并进一步实现请求分页式存储分配和地址转换过程。页面置换算法至少应实现先进先出(FIFO)、最近最久未使用(LRU)等算法。
●参考学时:9学时
●实验提示:
1、建立1个位示图,用来模拟内存的分配情况,位示图的位数与设定的物理块个数相同。程序启动时可利用一组随机0和1填充位示图,表示内存已被占用情况。
假设内存容量为64K,块大小为1K,则共有64个块,随机填充后的位示图可能的值如下:
该位示图表示内存的2(0字节第2位)、3(0字节第3位)、6(0字节第6位)、8(1字节第0位)、9(1字节第1位)、12(1字节第4位)、15(1字节第7位)…等块没有被占用。
2、创建进程时输入进程大小,并根据程序中设定的物理块大小为进程分配物理块,同时建立页表。例如,在上图基础上,若要建立一个大小为5000字节的进程,则:
计算出该进程共有“向上取整(5000/1024)=5”个页,需要占用5个内存块;
建立空的页表,即长度为5的一维整数数组;
从位示图中找出前5个“0”位在整个位示图中的位置号(即i字节j位为0,则该位的位置为8*i+j),并将这些号依次填入页表中,同时把前5个“0”改为“1”,以示对应内存块已经分配。
3、输入当前执行进程所要访问的逻辑地址,并将其转换成相应的物理地址。
4、进程退出时,根据其页表内容向位示图反向回填“0”。
5、扩充页表,将其变成支持请求和置换功能的二维页表(增加存在位等)。创建进程时可装入固定的前三页(或键盘输入初始装入页数,不同进程的装入个数可以不同),其余页装入到置换空间内(置换空间大小应为内存空间大小的1.5-2倍,对其还需建立独立的置换空间位示图)。
6、分别采用FIFO或LRU置换算法对地址转换过程中遇到的缺页现象进行页面置换,可将多次地址转换过程中所涉及到的页号视为进程的页面访问序列,从而计算置换次数和缺页率。
7、*可以在完成第六步的基础上实现OPT的页面置换算法,并加以比较。
●评分标准(满分15分):
●要求必须完成以下几个方面的内容(实验提示前4部分,10-12分):
●在第1部分基础上扩展;
●能够模拟内存的分页式分配和回收过程,可查看内存分配位示图和进程页表;
●可根据内存分配状态进行地址转换。
●如果实现以下要求(实验提示后3部分),有额外3-5分加分:
●能够模拟基于虚拟存储器的内存分配和回收过程,可查看交换空间位示图和扩展的页表;
●在虚拟存储器基础上完成地址转换,缺页时能够实现页面置换;
●页面置换过程中能够模拟FIFO、LRU置换算法,可将多次地址转换过程中所涉及到的页面视为进程的页面访问序列,从而计算置换次数和缺页率。
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<time.h>
#include<stdlib.h>
#define block_size 1024//块大小
#define mem_size 64//内存大小
#define swapspace_size 128//置换空间大小
#define lode_count 3//进程最多装入页数
#define maxsize 10//最大页表空间
int bitmap[64];
int swapbitmap[128];
using namespace std;
typedef struct Page_table//页表
{
int pageno,blockno,swapspaceno;//页号,块号,置换块号
int exists;//存在位,
}page_table[maxsize];
typedef struct PCB
{
int name;
int sizes; //进程大小
page_table pt;//一个进程的页表
int length;//当前页表个数
int fifo[3],lru[3],opt[3];
int optlist[maxsize];
int fifon,lrun,optn,listn;//fifo,lru,opt队列中页面的个数
double absent1,absent2,absent3;
double visit1,visit2;
struct PCB *next;
}PCB,*PCBlist;
PCBlist running;
void createbitmap()//创建位视图
{
int i;
srand(time(NULL));
for(i=0;i<mem_size;i++)
bitmap[i]=(rand()%2);
for(i=0;i<swapspace_size;i++)
swapbitmap[i]=(rand()%2);
}
void showbitmap()//显示位视图
{
cout<<"位示图"<<endl;
int i;
for(i=0;i<mem_size;i++)
{
cout<<bitmap[i];
if((i+1)%8==0)
cout<<endl;
}
cout<<"置换空间位示图"<<endl;
for(i=0;i<swapspace_size;i++)
{
cout<<swapbitmap[i];
if((i+1)%16==0)
cout<<endl;
}
}
void initpagetable(PCBlist &s)//初始化页表
{
PCBlist p;
p=s->next;
int i,j;
for(i=0;i<maxsize;i++)
{
p->pt[i].pageno=-1;
p->pt[i].blockno=-1;
p->pt[i].swapspaceno=-1;
p->pt[i].exists=0;
}
for(j=0;j<lode_count;j++)
{
p->fifo[j]=-1;
p->lru[j]=-1;
p->opt[j]=-1;
}
}
void createpage(PCBlist &s)//创建页表
{
PCBlist p;
p=s->next;
int m;
int i,j=0,k=0,t=0;
m= (int)ceil((double)p->sizes/(double)block_size);
p->length=m;
p->listn=p->fifon=p->lrun=p->optn=0;
p->absent1=p->absent2=p->absent3=0;
p->visit1=p->visit2=0;
if(m<=lode_count)
{
for(i=0;i<m;i++)//内存,页表 赋值
{
while((bitmap[j]!=0))//找位示图中的空闲内存
{
j++;
}
bitmap[j]=1;
p->pt[i].pageno=i;
p->pt[i].blockno=j;//j记录位置
p->pt[i].exists=1;
}
cout<<"该进程的页表如下:"<<endl;
cout<<"页号\t\t块号\t\t存在位\t\t置换块号"<<endl;
for(i=0;i<m;i++)//页表显示
{
cout<<p->pt[i].pageno<<'\t'<<'\t';
cout<<p->pt[i].blockno<<'\t'<<'\t';
cout<<p->pt[i].exists<<'\t'<<'\t';
cout<<p->pt[i].swapspaceno;
cout<<endl;
}
}
else
{
for(i=0;i<lode_count;i++)
{
while(bitmap[k]!=0)//找位示图中的空闲内存
{
k++;
}
bitmap[k]=1;//修改位示图
p->pt[i].pageno=i;
p->pt[i].blockno=k;
p->pt[i].exists=1;