- 介绍
- Demo
就是一个仿真,一般来说这东西知道个原理就差不多了。
但极端需求的情况下可能需要自己实现一个,例如写操作系统的时候。
下边是部分代码
PT.h
#pragma once #include#include #include class PT { public: typedef struct _PTE { //块号 int nframeNum; //是否有效 bool bValid; // bool bDirty; //访问次数 int nAccessCount; }PTE, *PPTE; enum REPLACEMENT_ALGORITHM { OPT = 0, CLOCK, FIFO, RANDOM }; typedef struct _PHYSICAL { char* p; //OPT算法专用 int nCount; //CLOCK算法专用 bool bSign; }PHYSICAL, *PPHYSICAL; public: PT(); ~PT(); //初始化页表 void Init(int nframeNum); //设置页面置换算法 void SetPageReplacement(const char* p); int MMU(int addr, char type); //页面替换算法 int PageReplacement(); int PageOPT(); int PageCLOCK(); int PageFIFO(); int PageRandom(); void SwapRead(int nPageNum, int nframeNum); void SwapWrite(int nPageNum, int nframeNum); private: std::vector m_vPT; std::vector m_vPhysicalAddr; std::vector m_vFT; std::vector m_vDisk; REPLACEMENT_ALGORITHM m_pa; int m_nUsed; public: //状态信息 int m_nPageFault; int m_nWritesToDisk; int m_nPageNum; };
PT.cpp
#include "PT.h"
PT::PT()
{
m_nUsed = 0;
m_nPageFault = 0;
m_nWritesToDisk = 0;
m_nPageNum = 0;
}
PT::~PT()
{
}
//初始化页表
void PT::Init(int nframeNum)
{
//4G / 2K
int nPageSize = 1024 * 2;
m_nPageNum = (1024*1024*1024*1) / (1024 * 2);
for (int i = 0; i < m_nPageNum; i++)
{
//页表项初始化
PTE pte;
pte.nframeNum = i;
pte.bValid = false;
pte.bDirty = false;
pte.nAccessCount = 0;
m_vPT.push_back(pte);
//磁盘初始化
char* p = new char[nPageSize];
memset(p, 0, nPageSize);
m_vDisk.push_back(p);
}
for (int i = 0; i < nframeNum; i++)
{
//物理内存初始化
PHYSICAL physical;
physical.nCount = 0;
physical.p = new char[nPageSize];
memset(physical.p, 0, nPageSize);
m_vPhysicalAddr.push_back(physical);
m_vFT.push_back(-1);
}
}
//设置页面置换算法
void PT::SetPageReplacement(const char* p)
{
if (strcmp(p, "opt") == 0)
{
m_pa = OPT;
}
else if (strcmp(p, "clock") == 0)
{
m_pa = CLOCK;
}
else if (strcmp(p, "fifo") == 0)
{
m_pa = FIFO;
}
else if (strcmp(p, "rand") == 0)
{
srand(time(NULL));
m_pa = RANDOM;
}
}
int PT::MMU(int addr, char type)
{
//计算页号和偏移
int nPageNum = addr >> 11;
int nOffset = addr - (nPageNum << 11);
if (nPageNum >= m_vPT.size())
{
//超出内存块
return -1;
}
//获取物理块号
int nframeNum = 0;
if (m_vPT[nPageNum].bValid == true)
{
nframeNum = m_vPT[nPageNum].nframeNum;
}
else
{
nframeNum = -1;
}
m_vPT[nPageNum].nAccessCount++;
//获取物理地址
int nPhysicalAddr = 0;
if (nframeNum >= 0)
{
nPhysicalAddr = (int)m_vPhysicalAddr[nframeNum].p + nOffset;
m_vPhysicalAddr[nframeNum].bSign = true;
m_vPhysicalAddr[nframeNum].nCount++;
return nPhysicalAddr;
}
//判断内存块是否没写满
if (m_nUsed < m_vPhysicalAddr.size())
{
//没写满
nframeNum = m_nUsed;
m_nUsed++;
m_vPT[nPageNum].nframeNum = nframeNum;
m_vPT[nPageNum].bValid = true;
m_vPT[nPageNum].bDirty = false;
m_vFT[nframeNum] = nPageNum;
}
else
{
//写满了 需要页面置换
nframeNum = PageReplacement();
int nOldPage = m_vFT[nframeNum];
if (m_vPT[nOldPage].bValid == true)
{
if (m_vPT[nOldPage].bDirty == true)
{
//swap write
SwapWrite(nOldPage, nframeNum);
}
m_vPT[nOldPage].bValid = false;
m_vPT[nOldPage].bDirty = false;
}
m_vFT[nframeNum] = nPageNum;
m_vPT[nPageNum].nframeNum = nframeNum;
m_vPT[nPageNum].bValid = true;
m_vPT[nPageNum].bDirty = false;
//swap read
SwapRead(nPageNum, nframeNum);
m_nPageFault++;
}
if (type == 'S' || type == 'M')
{
m_vPT[nPageNum].bDirty = true;
}
nPhysicalAddr = (int)m_vPhysicalAddr[nframeNum].p + nOffset;
return nPhysicalAddr;
}
//页面替换算法
int PT::PageReplacement()
{
switch (m_pa)
{
case OPT:
return PageOPT();
break;
case CLOCK:
return PageCLOCK();
break;
case FIFO:
return PageFIFO();
break;
case RANDOM:
return PageRandom();
break;
}
return 0;
}
int PT::PageOPT()
{
int nMin = m_vPhysicalAddr[0].nCount;
int nMax = m_vPhysicalAddr[0].nCount;
int nMinIndex = 0;
int nMaxIndex = 0;
for (int i = 0; i < m_vPhysicalAddr.size(); i++)
{
if (nMin > m_vPhysicalAddr[i].nCount)
{
nMin = m_vPhysicalAddr[i].nCount;
nMinIndex = i;
}
if (nMax < m_vPhysicalAddr[i].nCount)
{
nMax = m_vPhysicalAddr[i].nCount;
nMaxIndex = i;
}
}
m_vPhysicalAddr[nMinIndex].nCount = m_vPhysicalAddr[nMaxIndex].nCount + 1;
return nMinIndex;
}
int PT::PageCLOCK()
{
int nIndex = 0;
for (auto it : m_vPhysicalAddr)
{
if (it.bSign == false)
{
break;
}
it.bSign = false;
nIndex++;
}
return 0;
}
int PT::PageFIFO()
{
static int cur = 0;
int next = cur++;
if (cur >= m_vPhysicalAddr.size())
{
cur = 0;
}
return next;
}
int PT::PageRandom()
{
int rd = rand() % m_vPhysicalAddr.size();
return rd;
}
void PT::SwapRead(int nPageNum, int nframeNum)
{
m_vPhysicalAddr[nframeNum].p = m_vDisk[nPageNum];
}
void PT::SwapWrite(int nPageNum, int nframeNum)
{
m_vDisk[nPageNum] = m_vPhysicalAddr[nframeNum].p;
m_nWritesToDisk++;
}
简单使用
PT pt;
pt.Init(nframeNum);
pt.SetPageReplacement(strAlgorithm.c_str());
int i = 0;
for (auto it : vIns)
{
pt.MMU(it.addr, it.type);
}



