目录
代码:
#include <iostream>
using namespace std;
#define Num 10 //进程执行需要的页面数量
#define Len 5 //为进程分配的物理帧数
int M = Len - 1; //M表示内存中缓冲帧指针
int N = 0; //N表示内存中下一个牺牲帧的地址
int Exchange[2 * Len]; //交换空间,其中存放换出的地址序列
int Sum = 0; //Sum表示交换空间中的页面数量
int method = 1; //使用的算法,此处默认为FIFO
class Memory //进程内存的数据结构
{
public:
int page; //物理内存中存放的页号
bool valid; //有效无效位;无效为0,有效为1
bool dirty; //修改为:未修改过为0,修改过为1
Memory()
{
page = 0;
valid = 0;
dirty = 0;
}
};
Memory memory[Len]; //为进程分配的内存空间
class Process //进程相关的数据
{
public:
int page;
bool write;
int times;
Process()
{
page = 0;
write = 0;
times = 0;
}
};
Process Page[Num]; //进程运行中需要的页面号与相关操作
void display(int num)
{
cout << "\n____________________________这是第" << num << "次页面分配________________________\n"
<< endl;
cout << "当前内存中帧 对应的页面号 脏位:" << endl;
for (int i = 0; i < Len; i++)
if (memory[i].valid == 1 && i != M)
cout << i << "\t\t" << memory[i].page << "\t\t" << memory[i].dirty << endl;
cout << "\n当前缓冲区的位置" << endl;
cout << M << endl;
cout << "\n当前交换空间中页面号" << endl;
for (int i = 0; i < Sum; i++)
cout << Exchange[i] << " ";
cout << "\n\n\n\n"
<< endl;
}
void set_method()
{
while (1)
{
cout << "选择一种页面置换算法:\n*按下1选择FIFO算法\n*按下2选择LRU算法" << endl;
cin >> method;
if (method > 0 && method < 3)
return;
else
continue;
}
}
void CreatPage()
{
cout << "\n该进程在运行过程中需要的目标序列与读写操作" << endl;
for (int i = 0; i < Num; i++)
{
Page[i].page = rand() % Num;
Page[i].write = rand() % 2; //当前情况下为读写页面
}
cout << "\n随机生成的内存引用串\n"
<< endl;
for (int i = 0; i < Num; i++)
{
cout << "引用页码:" << Page[i].page << " "
<< "读写操作:" << Page[i].write << "\n";
if (i == Num - 1)
{
cout << endl;
}
}
}
bool search(int a, int &c)
{
for (c = 0; c < Len; c++)
if (memory[c].valid == 1 && memory[c].page == a)
return true;
return false;
}
bool exchange(int a, int &e)
{
for (e = 0; e < Sum; e++)
if (Exchange[e] == a)
return true;
return false;
}
bool full(int &n)
{
//检查内存中的有效无效位,如果存在无效位且不为缓冲区,则未满
for (n = 0; n < Len; n++)
if (memory[n].valid == 0 && M != n)
{
return false;
}
return true;
}
int LRU()
{
int min = 0, mintime = Page[memory[0].page].times;
for (int i = 0; i < Len; i++)
{
if (Page[memory[i].page].times < mintime)
{
mintime = Page[memory[i].page].times;
min = i;
}
}
return min;
}
int main()
{
system("chcp 65001");
set_method();
CreatPage();
//读取内存引用串,模拟页面调度过程
for (int i = 0; i < Num; i++)
{
//输出当前内存引用
cout << "进程执行需要的页面号:\t" << Page[i].page;
if (Page[i].write)
cout << "\t写" << endl;
else
cout << "\t读" << endl;
int c;
//查询是否命中
if (search(Page[i].page, c))
{
cout << "\n命中当前页面" << endl;
cout << "当前页面:\t" << Page[i].page << "\t在内存的位置:\t" << c << endl;
if (Page[i].write)
memory[c].dirty = 1;
Page[memory[c].page].times++;
//判断当前页面是读,还是写
}
//未命中,开始页面置换
else
{
cout << "\n未命中当前页面" << endl;
int e;
//检查所需要的页面是否位于交换空间中
if (exchange(Page[i].page, e))
{
cout << "当前页面处于交换空间中" << endl;
//放出交换空间中的页面,同时调整交换空间的各页面
for (int i = e; i < Sum - 1; i++)
{
Exchange[i] = Exchange[i + 1];
}
Sum--;
//Page[memory[c].page].times++;
}
int n;
//检查当前内存是否已经占满,若没有,直接加入内存
if (!full(n))
{
memory[n].page = Page[i].page;
memory[n].valid = 1;
if (Page[i].write)
memory[n].dirty = 1;
else
memory[n].dirty = 0;
Page[memory[n].page].times++;
}
//内存已满,需要页面置换
else
{
//根据所选用的算法决定换出的页面
switch (method)
{
//先进先出算法
case 1:
{
memory[M].page = Page[i].page;
memory[M].valid = 1;
if (Page[i].write)
memory[M].dirty = 1;
else
memory[M].dirty = 0;
M = N;
N = (N + 1) % Len;
memory[M].valid = 0;
if (memory[M].dirty == 0 && Sum < 2 * Len)
{
Exchange[Sum] = memory[M].page;
Sum++;
}
}
break;
//LRU页面置换
case 2:
{
memory[M].page = Page[i].page;
memory[M].valid = 1;
if (Page[i].write)
memory[M].dirty = 1;
else
memory[M].dirty = 0;
N = LRU();
M = N;
memory[M].valid = 0;
Page[memory[M].page].times++;
if (memory[M].dirty == 0 && Sum < 2 * Len)
{
Exchange[Sum] = memory[M].page;
Sum++;
}
}
break;
default:
break;
}
}
}
//输出内存信息
display(i);
}
system("pause");
return 0;
}
虚拟存储实验README
1、完成虚拟存储的思路
* 基本功能:页面置换、数据缓冲、交换文件
* 页面置换:当为进程分配的内存帧不足时,需要按照页面置换的策略将一个页面进行换入换出操作
* 数据缓冲:系统保留一个空闲帧缓冲池,发生缺页错误在写出之前,所需页面就读到缓冲池的空闲帧,牺牲页面的帧被设定为新的空闲帧
* 交换文件:虚拟内存将不常使用的页面换出至交换空间,提高页面置换的效率
2、进程执行的基本思路
* 在内存中为进程分配了固定的内存空间;(其中包括一个空闲帧作为数据缓冲)
* 进程逐步执行对应的页面,如果页面不在内存中(发生缺页错误),就将其调入内存;如果可用的内存帧为0,就采用调入调出(页面置换)
* 注意对应进程执行的页面,需区分读、写,涉及到脏位与交换空间
* 数据缓冲buffer:在换入换出的过程中,可以先将目的页面换入数据缓冲中,并将选定的牺牲帧设定为空闲空间(已换出)
3、是用什么数据结构模拟虚拟内存调页?
用结构体模拟物理内存和逻辑内存,以全局变量模拟缓冲区和交换空间。
页表和物理外存,在本次实验中由于只有一个进程所以省略,以数组的下标关系取代表示。
4、FIFO算法和LRU算法。
FIFO:当物理内存已满,且请求调页时,取最早进入内存的帧牺牲。
LRU:当物理内存已满,且请求调页时,取最近最少使用的帧牺牲。
5、交换空间 交换空间是专门用于临时存储内存的一块磁盘空间,通常在页面调度和交换进程数据时使用,通常推荐交换空间的大小应该是物理内存的二到四倍。
当可执行程序开始运行时,它的映象会一页一页地从磁盘中换入,与此类似,当某些内存在一段时间内空闲,就可以把它们换出到交换空间中,这样就可以把空闲的RAM交给其他需要它的程序使用。在换入换出的过程中,可以将空闲帧中牺牲掉的帧放到交换空间中,提高读取速度
6、页面置换的基本思路:
* 随着指令的执行,如果发现目标页面不位于当前帧中,发生缺页中断;
* 首先对目的页面进行判断,判断其是否在交换空间中,若在则无需访问文件系统
* 接下来将目标页面调入数据缓冲的帧中,并寻找牺牲帧,将其设定为数据缓冲的帧;
* 最后在这个过程中,对牺牲页面脏位进行判定,如果其未被修改,则将其放置交换空间