虚拟内存的仿真

虚拟内存的仿真

介绍

就是一个仿真,一般来说这东西知道个原理就差不多了。
但极端需求的情况下可能需要自己实现一个,例如写操作系统的时候。
下边是部分代码

Demo

PT.h

#pragma once
#include <iostream>
#include <vector>
#include <time.h>


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<PTE> m_vPT;
	std::vector<PHYSICAL> m_vPhysicalAddr;
	std::vector<int> m_vFT;
	std::vector<char*> 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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值