【計算機操作系統】存儲管理的 C++ 實現(附源碼)

一、實驗目的

  存儲管理的主要功能之一是合理地分配空間。請求頁式管理是一種常用的虛擬存儲管理技術。本實驗的目的是通過請求頁式管理中頁面置換算法模擬設計,瞭解虛擬存儲技術的特點,掌握請求頁式存儲管理的頁面置換算法。因爲源碼中我對一些關鍵步驟的註釋已經比較清晰了,所以在本文中不會再對每一個細節都進行分析,只分析整體的代碼結構和所使用到的設計模式。

  博客內所有文章均爲 原創,所有示意圖均爲 原創,若轉載請附原文鏈接。

二、實驗內容

2.1 實現多種頁面置換算法並比較算法優劣

  • (1)通過計算不同算法的命中率比較算法的優劣。同時也考慮了用戶內存容量對命中率的影響(命中率 = 1 - 頁面失效次數 ÷ 頁地址流長度)。頁面失效次數爲每次訪問相應指令時,該指令所對應的頁不在內存中的次數。在本實驗中,假定頁面大小爲1k,用戶虛存容量爲32k,用戶內存容量爲4頁到32頁。

  • (2)produce_addstream 通過隨機數產生一個指令序列,共320條指令。
    A、指令的地址按下述原則生成:
     1)50%的指令是順序執行的
     2)25%的指令是均勻分佈在前地址部分
     3)25%的指令是均勻分佈在後地址部分
    B、具體的實施方法是:
     1)在[0,319]的指令地址之間隨機選取一起點m;
     2)順序執行一條指令,即執行地址爲m+1的指令;
     3)在前地址[0,m+1]中隨機選取一條指令並執行,該指令的地址爲m’;
     4)順序執行一條指令,地址爲m’+1的指令
     5)在後地址[m’+2,319]中隨機選取一條指令並執行;
     6)重複上述步驟1)~5),直到執行320次指令
    C、將指令序列變換稱爲頁地址流
     在用戶虛存中,按每k存放10條指令排列虛存地址,即320條指令在虛存中的存放方式爲:
     第0條~第9條指令爲第0頁(對應虛存地址爲[0,9]);
     第10條~第19條指令爲第1頁(對應虛存地址爲[10,19]);
     。。。。。。
     第310條~第319條指令爲第31頁(對應虛存地址爲[310,319]);
     按以上方式,用戶指令可組成32頁。

  • (3)計算並輸出下述算法在不同內存容量下的命中率。
      1)最佳置換算法(OPT);
      2)先進先出算法(FIFO);
      3)最近最久未使用頁面置換(LRU);
      4)最少使用頁面淘汰算法(LFU)

三、流程圖

3.1 算法流程

在這裏插入圖片描述

四、設計思想

4.1 設計思路

  該實驗中需要實現四種頁面置換算法,分別爲 OPT、FIFO、LRU和LFU,通過分析發現這四種算法中都存在一種優先級的關係,只不過優先級的屬性不同,比如在LRU算法中,優先級爲最近一次訪問距離現在的時間,即頁面最近一次訪問距離現在的時間越短其優先級越高,而對於LFU算法,優先級頁面被訪問的次數,即用戶內存中頁面被訪問的次數越多,其優先級也就越高,越不容易被淘汰,而FIFO算法中的優先級就是進入用戶空間的時間,時間越短優先級越高,OPT中的優先級就是頁面下次被訪問據當前的時間,時間越短優先級越高。
  當我們找到了這幾種算法中的優先級關係後,通過分析可以發現優先級隊列可以很好的滿足這個需求,而對於LRU算法的實現其實最簡單的方法是如果被訪問的頁面存在於用戶空間中,那麼就將其提升至隊尾(隊尾入頁面,隊頭出頁面),但是爲了保證多個算法的統一性,還是決定採用相同的抽象算法來實現。
  而對於整體的代碼結構設計,可以採用 模板方法設計模式 + 策略設計模式 的方法來進行實現,增強算法整體的靈活性、可擴展性和可維護性。

4.2 代碼分析

  首先是Page結構體,該結構體保存了 OPT、LRU 和 LFU 算法所需的各項屬性。

struct Page
{
	Page() : elapsed_time_since_last_visit(0), used_count(0) {}
	int virtual_memory_index;
	// OPT
	TimeSlice be_used_again_time_;
	// LRU
	TimeSlice elapsed_time_since_last_visit;
	// LFU
	int used_count;
};

  其次是 UserMemorySpace 類,該類是用戶內存空間的抽象,提供了一個模板參數 PriorityCmp,用來指定優先級隊列中的優先級關係定義,並且在它的屬性中存在 page_index_array_ 數組和 memory_queue_優先級隊列,其中前者是保存所有的虛擬頁面信息,PageInfo 中持有 Page 的引用,同時記錄該頁面是否存在於用戶空間優先級隊列中,而後者的 memory_queue_ 就是物理用戶內存空間,前者的存在主要是了便於對物理用戶內存空間內頁面的查找定位,而該類的功能總結起來就是提供了對物理用戶內存空間的基礎操作(確定一個頁面是否存在於用戶空間中,獲取一個頁面,插入一個頁面等等)。

template<typename PriorityCmp>
class UserMemorySpace
{
public:
	struct PageInfo
	{
		bool in_user_memory = false;
		PagePtr page = new Page();
	};

	typedef PageInfo * PageInfoPtr;

	UserMemorySpace(int user_memory_size, int virtual_memory_size)
		: user_memory_size_(user_memory_size)
		, virtual_memory_size_(virtual_memory_size)
		, memory_queue_(new std::priority_queue<PagePtr, std::vector<PagePtr>, PriorityCmp>())
		, page_index_array_(new std::vector<PageInfoPtr>(virtual_memory_size));

	inline void initPageIndexArray();
	void push(int virtual_page_index);
	PagePtr pop();
	inline PageInfoPtr getPageInfo(int virtual_page_index);
	inline PagePtr getPage(int virtual_page_index);
	inline bool pageInUserMemory(int virtual_page_index);
	void freshPageOrder();
	std::vector<PagePtr> * getPagesInUserMemory();

private:
	int user_memory_size_;
	int virtual_memory_size_;
	// help find page in memory queue
	std::vector<PageInfoPtr> * page_index_array_;
	std::priority_queue<PagePtr, std::vector<PagePtr>, PriorityCmp> * memory_queue_;
};

  接下來是頁面置換算法,這裏採用了模板方法設計模式,其中PageReplacementAlgorithm爲所有是算法的抽象基類,不提供具體實現,只規定算法所必須實現的方法,且其持有一個UserMemorySpace的引用。

// 頁面置換算法基類
class PageReplacementAlgorithm;

// 最佳頁面置換算法
class OPTPageReplacementAlgorithm : public PageReplacementAlgorithm;

// 先來先服務頁面置換算法
class FIFOPageReplacementAlgorithm : public PageReplacementAlgorithm;

// LRU 頁面置換算法
class LRUPageReplacementAlgorithm : public PageReplacementAlgorithm;

// LFU 頁面置換算法
class LFUPageReplacementAlgorithm : public PageReplacementAlgorithm;

  最後兩個模塊類,PageReplacement是對頁面置換邏輯的封裝,主要用於聚合PageReplacementAlgorithm和UserMemorySpace,並設置相應的物理用戶內存空間的大小,而PageReplacementWrapper是對PageReplacement的進一步封裝,指引用戶輸入相應的數據(具體實現請見源碼)。

template<typename PageReplacementAlgorithm, typename PriorityCmp>
class PageReplacement;

class PageReplacementWrapper;

五、代碼實現

#include <iostream>
#include <string>
#include <vector>
#include <queue>
#include <cstdlib>
#include <ctime>
#include <unistd.h>
#include <iomanip>

class Util
{
public:
	static inline int getRandom(const int min_val, const int max_val, int match)
	{
		srand(time(0) + match);
		return ((max_val - min_val - 1) == 0) ? min_val : rand() % (max_val - min_val - 1) + min_val;
	}
};

typedef int TimeSlice;
int page_replacement_count = 0;
std::vector<double> * ratio = new std::vector<double>(28, 0);

struct Page
{
	Page() : elapsed_time_since_last_visit(0), used_count(0) {}
	int virtual_memory_index;
	// OPT
	TimeSlice be_used_again_time_;
	// LRU
	TimeSlice elapsed_time_since_last_visit;
	// LFU
	int used_count;
};

typedef Page * PagePtr;

template<typename PriorityCmp>
class UserMemorySpace
{
public:
	struct PageInfo
	{
		bool in_user_memory = false;
		PagePtr page = new Page();
	};

	typedef PageInfo * PageInfoPtr;

	UserMemorySpace(int user_memory_size, int virtual_memory_size)
		: user_memory_size_(user_memory_size)
		, virtual_memory_size_(virtual_memory_size)
		, memory_queue_(new std::priority_queue<PagePtr, std::vector<PagePtr>, PriorityCmp>())
		, page_index_array_(new std::vector<PageInfoPtr>(virtual_memory_size))
	{
		initPageIndexArray();
	}

	inline void initPageIndexArray()
	{
		for (int i = 0; i < virtual_memory_size_; ++i)
		{
			(*page_index_array_)[i] = new PageInfo();
			getPage(i)->virtual_memory_index = i;
		}
	}

	void push(int virtual_page_index)
	{
		// if page already in user memory
		PageInfoPtr pip = getPageInfo(virtual_page_index);
		if (pip->in_user_memory)
		{
			//std::cout << "virtual page " << virtual_page_index << " already in user memory." << std::endl;
			return;
		}

		page_replacement_count++;
		if (memory_queue_->size() >= user_memory_size_) pop();
		PagePtr page = getPage(virtual_page_index);
		memory_queue_->push(page);
		pip->in_user_memory = true;
		//std::cout << "virtual page " << virtual_page_index << " swap in." << std::endl;
	}

	PagePtr pop()
	{
		PagePtr page = memory_queue_->top();
		memory_queue_->pop();
		getPageInfo(page->virtual_memory_index)->in_user_memory = false;

		//std::cout << "virtual page " << page->virtual_memory_index << " swap out." << std::endl;
		return page;
	}

	inline PageInfoPtr getPageInfo(int virtual_page_index)
	{
		return (*page_index_array_)[virtual_page_index];
	}

	inline PagePtr getPage(int virtual_page_index)
	{
		return getPageInfo(virtual_page_index)->page;
	}

	inline bool pageInUserMemory(int virtual_page_index)
	{
		return getPageInfo(virtual_page_index)->in_user_memory;
	}

	void freshPageOrder()
	{
		std::vector<PagePtr> * pages = new std::vector<PagePtr>();
		while (!memory_queue_->empty())
		{
			// while priority equal,order by enqueue order
			pages->push_back(memory_queue_->top());
			memory_queue_->pop();
		}
		for (PagePtr page : *pages) memory_queue_->push(page);
		delete pages;
	}

	std::vector<PagePtr> * getPagesInUserMemory()
	{
		std::vector<PagePtr> * pages = new std::vector<PagePtr>();
		for (PageInfoPtr pi : *page_index_array_)
			if (pi->in_user_memory) pages->push_back(pi->page);
		return pages;
	}

private:
	int user_memory_size_;
	int virtual_memory_size_;
	// help find page in memory queue
	std::vector<PageInfoPtr> * page_index_array_;
	std::priority_queue<PagePtr, std::vector<PagePtr>, PriorityCmp> * memory_queue_;
};

class PageReplacementAlgorithm
{
public:
	virtual void setPageAddressStream(std::vector<int> * page_address_stream) {};
	virtual void setCurrentPageIndexOfPageAddressStream(int index) {};
	virtual PagePtr getPage(int virtual_memory_index) = 0;
};

class OPTPageReplacementAlgorithm : public PageReplacementAlgorithm
{
public:
	struct PriorityCmp
	{
		bool operator()(PagePtr p1, PagePtr p2)
		{
			return p1->be_used_again_time_ < p2->be_used_again_time_;
		}
	};

	OPTPageReplacementAlgorithm(UserMemorySpace<PriorityCmp> * user_memory_space)
		: user_memory_space_(user_memory_space)
	{}

	void setPageAddressStream(std::vector<int> * page_address_stream)
	{
		page_address_stream_ = page_address_stream;
	}

	void setCurrentPageIndexOfPageAddressStream(int index)
	{
		current_page_index_of_page_address_stream_ = index;
	}

	PagePtr getPage(int virtual_memory_index)
	{
		PagePtr page = user_memory_space_->getPage(virtual_memory_index);

		updatePageBeAgainUsedTime();
		user_memory_space_->freshPageOrder();

		user_memory_space_->push(virtual_memory_index);

		current_page_index_of_page_address_stream_++;

		return page;
	}

	void updatePageBeAgainUsedTime()
	{
		std::vector<PagePtr> * pages = user_memory_space_->getPagesInUserMemory();
		for (PagePtr p : *pages)
			p->be_used_again_time_ = getPageNextUsedTimeFromPageAddressStream(p->virtual_memory_index) 
				- current_page_index_of_page_address_stream_;
	}

	int getPageNextUsedTimeFromPageAddressStream(int virtual_memory_index)
	{
		for (int i = current_page_index_of_page_address_stream_ + 1; i < page_address_stream_->size(); ++i)
			if ((*page_address_stream_)[i] == virtual_memory_index) return i;
		return page_address_stream_->size();
	}

private:
	int current_page_index_of_page_address_stream_ = 0;
	std::vector<int> * page_address_stream_;
	UserMemorySpace<PriorityCmp> * user_memory_space_;
};

class FIFOPageReplacementAlgorithm : public PageReplacementAlgorithm
{
public:
	struct PriorityCmp
	{
		bool operator()(PagePtr p1, PagePtr p2)
		{
			return false;
		}
	};

	FIFOPageReplacementAlgorithm(UserMemorySpace<PriorityCmp> * user_memory_space)
		: user_memory_space_(user_memory_space)
	{}

	PagePtr getPage(int virtual_memory_index)
	{
		PagePtr page = user_memory_space_->getPage(virtual_memory_index);
		user_memory_space_->push(virtual_memory_index);
		return page;
	}

private:
	UserMemorySpace<PriorityCmp> * user_memory_space_;
};

class LRUPageReplacementAlgorithm : public PageReplacementAlgorithm
{
public:
	struct PriorityCmp
	{
		bool operator()(PagePtr p1, PagePtr p2)
		{
			return p1->elapsed_time_since_last_visit < p2->elapsed_time_since_last_visit;
		}
	};

	LRUPageReplacementAlgorithm(UserMemorySpace<PriorityCmp> * user_memory_space)
		: user_memory_space_(user_memory_space)
	{}

	PagePtr getPage(int virtual_memory_index)
	{
		PagePtr page = user_memory_space_->getPage(virtual_memory_index);
		// this page may already in user memory,avoid repeat elapsed_time_since_last_visit++
		// there should judge this page whether in user memory
		page->elapsed_time_since_last_visit = user_memory_space_->pageInUserMemory(virtual_memory_index) ? -1 : 0;

		std::vector<PagePtr> * pages = user_memory_space_->getPagesInUserMemory();
		for (PagePtr p : *pages)
			p->elapsed_time_since_last_visit++;
		user_memory_space_->freshPageOrder();

		user_memory_space_->push(virtual_memory_index);

		return page;
	}

private:
	UserMemorySpace<PriorityCmp> * user_memory_space_;
};

class LFUPageReplacementAlgorithm : public PageReplacementAlgorithm
{
public:
	struct PriorityCmp
	{
		bool operator()(PagePtr p1, PagePtr p2)
		{
			return p1->used_count > p2->used_count;
		}
	};

	LFUPageReplacementAlgorithm(UserMemorySpace<PriorityCmp> * user_memory_space)
		: user_memory_space_(user_memory_space)
	{}

	PagePtr getPage(int virtual_memory_index)
	{
		PagePtr page = user_memory_space_->getPage(virtual_memory_index);
		if (user_memory_space_->pageInUserMemory(virtual_memory_index)) page->used_count++;
		else page->used_count = 1;

		user_memory_space_->freshPageOrder();
		user_memory_space_->push(virtual_memory_index);

		return page;
	}

private:
	UserMemorySpace<PriorityCmp> * user_memory_space_;
};


template<typename PageReplacementAlgorithm, typename PriorityCmp>
class PageReplacement
{
public:
	PageReplacement<PageReplacementAlgorithm, PriorityCmp>(){}

	bool doPageReplacement()
	{
		for (int user_mem_space = 4; user_mem_space <= 32; ++user_mem_space)
		{
			page_replacement_count = 0;
			user_memory_space_ = new UserMemorySpace<PriorityCmp>(user_mem_space, 32);
			page_replacement_algorithm_ = new PageReplacementAlgorithm(user_memory_space_);
			page_replacement_algorithm_->setPageAddressStream(page_address_stream_);

			for (int index = 0; index < page_address_stream_->size(); ++index)
			{
				page_replacement_algorithm_->setCurrentPageIndexOfPageAddressStream(index);
				page_replacement_algorithm_->getPage((*page_address_stream_)[index]);
				current_page_index_of_page_address_stream_ = index;
			}

			double cache_hit_ratio = 1 - page_replacement_count/(page_address_stream_->size() / 1.0);
			//std::cout << "user memory space is " << user_mem_space << "k, cache hit ratio " << cache_hit_ratio << std::endl;
			//std::cout << cache_hit_ratio << ",";
			(*ratio)[user_mem_space - 4] = cache_hit_ratio;
		}

		return true;
	}

	void setPageAddressStream(std::vector<int> * page_address_stream)
	{
		page_address_stream_ = page_address_stream;
	}

private:
	int current_page_index_of_page_address_stream_ = 0;
	std::vector<int> * page_address_stream_;
	UserMemorySpace<PriorityCmp> * user_memory_space_;
	PageReplacementAlgorithm * page_replacement_algorithm_;
};

class PageReplacementWrapper
{
public:
	PageReplacementWrapper()
	{
		opt_page_replacement_ = new PageReplacement<OPTPageReplacementAlgorithm, OPTPageReplacementAlgorithm::PriorityCmp>();
		fifo_page_replacement_ = new PageReplacement<FIFOPageReplacementAlgorithm, FIFOPageReplacementAlgorithm::PriorityCmp>();
		lru_page_replacement_ = new PageReplacement<LRUPageReplacementAlgorithm, LRUPageReplacementAlgorithm::PriorityCmp>();
		lfu_page_replacement_ = new PageReplacement<LFUPageReplacementAlgorithm, LFUPageReplacementAlgorithm::PriorityCmp>();
	}

	bool doPageReplacement()
	{
		produceAddstream(320);
		//produceTestAddstream();
		choosePageReplacementAlgorithm();
		return true;
	}

	bool doTest()
	{
		std::vector<double> * opt = new std::vector<double>(28);
		std::vector<double> * fifo = new std::vector<double>(28);
		std::vector<double> * lru = new std::vector<double>(28);
		std::vector<double> * lfu = new std::vector<double>(28);

		for (int i = 0; i < 100; ++i)
		{
			produceAddstream(320);
			
			opt_page_replacement_->setPageAddressStream(page_address_stream_);
			opt_page_replacement_->doPageReplacement();
			for (int i = 0; i < opt->size(); ++i)
				(*opt)[i] += (*ratio)[i];
			ratio->clear();


			fifo_page_replacement_->setPageAddressStream(page_address_stream_);
			fifo_page_replacement_->doPageReplacement();
			for (int i = 0; i < fifo->size(); ++i)
				(*fifo)[i] += (*ratio)[i];
			ratio->clear();


			lru_page_replacement_->setPageAddressStream(page_address_stream_);
			lru_page_replacement_->doPageReplacement();
			for (int i = 0; i < lru->size(); ++i)
				(*lru)[i] += (*ratio)[i];
			ratio->clear();


			lfu_page_replacement_->setPageAddressStream(page_address_stream_);
			lfu_page_replacement_->doPageReplacement();
			for (int i = 0; i < lfu->size(); ++i)
				(*lfu)[i] += (*ratio)[i];
			ratio->clear();
		}

		for (double d : *opt)
			std::cout << (d / 100) << ",";
		std::cout << std::endl;

		for (double d : *fifo)
			std::cout << (d / 100) << ",";
		std::cout << std::endl;

		for (double d : *lru)
			std::cout << (d / 100) << ",";
		std::cout << std::endl;

		for (double d : *lfu)
			std::cout << (d / 100) << ",";
		std::cout << std::endl;
	}

	void choosePageReplacementAlgorithm()
	{
		std::cout << "There are algorithms in the program" << std::endl;
		std::cout << "1.Optimization algorithm" << std::endl;
		std::cout << "2.First in first out algorithm" << std::endl;
		std::cout << "3.Least recently used algorithm" << std::endl;
		std::cout << "4.Least frequently used algorithm" << std::endl;
		std::cout << "Select an algorithm number, please." << std::endl;

		int pra = 1;
		bool continue_do = false;
		do {

			do {
				std::cin >> pra;
				switch (pra)
				{
				case 1:
					std::cout << "current is Optimization algorithm" << std::endl;
					opt_page_replacement_->setPageAddressStream(page_address_stream_);
					opt_page_replacement_->doPageReplacement();
					break;

				case 2:
					std::cout << "current is First in first out algorithm" << std::endl;
					fifo_page_replacement_->setPageAddressStream(page_address_stream_);
					fifo_page_replacement_->doPageReplacement();
					break;

				case 3:
					std::cout << "current is Least recently used algorithm" << std::endl;
					lru_page_replacement_->setPageAddressStream(page_address_stream_);
					lru_page_replacement_->doPageReplacement();
					break;

				case 4:
					std::cout << "current is Least frequently used algorithm" << std::endl;
					lfu_page_replacement_->setPageAddressStream(page_address_stream_);
					lfu_page_replacement_->doPageReplacement();
					break;

				default:
					std::cout << "there is not the algorithm in the program" << std::endl;
					break;
				}
			} while (pra < 1 || pra > 4);

			std::cout << "do you try again with another algorithm(y/n)" << std::endl;
			char ch = 'n';
			std::cin >> ch;
			continue_do = (ch == 'y');
		} while (continue_do);

	}

	void produceAddstream(int addrNum)
	{
		std::cout << "Start memory management." << std::endl;
		std::cout << "Producing address flow, wait for while, please." << std::endl;

		instruction_sequence_ = new std::vector<int>();
		while (instruction_sequence_->size() != addrNum)
		{
			int m = Util::getRandom(0, addrNum - 1, instruction_sequence_->size());
			instruction_sequence_->push_back(m + 1);
			if (instruction_sequence_->size() == addrNum) break;

			int m_ = Util::getRandom(0, m + 1, instruction_sequence_->size());
			instruction_sequence_->push_back(m_);
			instruction_sequence_->push_back(m_ + 1);
			if (instruction_sequence_->size() == addrNum) break;

			int n = Util::getRandom(m_ + 2, addrNum - 1, instruction_sequence_->size());
			instruction_sequence_->push_back(n);
		}

		page_address_stream_ = new std::vector<int>();
		for (int ins : *instruction_sequence_)
		{
			page_address_stream_->push_back(ins / 10);
			// std::cout << ins/10 << " ";
		}
	}

	void produceTestAddstream()
	{
		page_address_stream_ = new std::vector<int>();
		// {7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1}
		page_address_stream_->push_back(7);
		page_address_stream_->push_back(0);
		page_address_stream_->push_back(1);
		page_address_stream_->push_back(2);
		page_address_stream_->push_back(0);

		page_address_stream_->push_back(3);
		page_address_stream_->push_back(0);
		page_address_stream_->push_back(4);
		page_address_stream_->push_back(2);
		page_address_stream_->push_back(3);

		page_address_stream_->push_back(0);
		page_address_stream_->push_back(3);
		page_address_stream_->push_back(2);
		page_address_stream_->push_back(1);
		page_address_stream_->push_back(2);

		page_address_stream_->push_back(0);
		page_address_stream_->push_back(1);
		page_address_stream_->push_back(7);
		page_address_stream_->push_back(0);
		page_address_stream_->push_back(1);
	}

private:
	std::vector<int> * instruction_sequence_;
	std::vector<int> * page_address_stream_;
	PageReplacement<OPTPageReplacementAlgorithm, OPTPageReplacementAlgorithm::PriorityCmp> * opt_page_replacement_;
	PageReplacement<FIFOPageReplacementAlgorithm, FIFOPageReplacementAlgorithm::PriorityCmp> * fifo_page_replacement_;
	PageReplacement<LRUPageReplacementAlgorithm, LRUPageReplacementAlgorithm::PriorityCmp> * lru_page_replacement_;
	PageReplacement<LFUPageReplacementAlgorithm, LFUPageReplacementAlgorithm::PriorityCmp> * lfu_page_replacement_;
};

六、運行結果

6.1 初始化

在這裏插入圖片描述

6.2 OPT

在這裏插入圖片描述

6.3 FIFO

在這裏插入圖片描述

6.4 LRU

在這裏插入圖片描述

6.5 LFU

在這裏插入圖片描述

七、思考

7.1 比較各種算法的命中率

在這裏插入圖片描述
  上圖爲循環執行 100 次時各算法的命中率可視化,其中 x 軸爲用戶內存大小,y 軸爲緩存命中率。這個問題可以通過上述的可視化視圖來進行分析,通過上面的運行結果的可視化視圖我們可以看到在循環運行100次後,FIFO的平均緩存命中率高於LRU算法,這有點違揹我們以往的知識,即LRU是對FIFO的優化算法,緩存命中率應當高於FIFO。通過分析後,我認爲主要是由於該實驗中的隨機指令生成算法造成的。
  我們可以發現該隨機算法雖然是保證了25%的指令位於前部,25%的指令位於後部,50%的指令是連續的,但是我們可以發現該生成算法五步爲一輪,每一輪在第一步都會重新確定起點,這導致雖然整體中又50%的指令是連續的,但都是僅有兩條是連續的。
  而我們平時所述得LRU算法優於FIFO算法,主要是因爲在實際工程中,指令的執行大多是順序執行的,存在局部性原理,在這裏可能剛剛被訪問到的指令很快又會被訪問到,所以此時LRU算法是最高效的。在後續我也測試了增加指令的重複性和連續性,LRU的算法命中率上升。

7.2 分析當用戶內存容量增加時對命中率的影響

  通過 7.1 中的圖可以看到,當用戶內存容量越大時,命中率是越高的,因爲用戶內存可常駐的物理內存越來越多,缺頁次數減少,當用戶物理內存和虛擬內存相等時,每個物理頁面只需調入一次用戶內存,即可一直常駐用戶內存。

八、結尾

  如果本文描述的內容或使用的代碼存在任何問題,請及時聯繫我或在本篇文章的下面進行評論,我會本着對每一位學技術同學的負責態度立即修改。在後續還會有三篇計算機操作系統的算法 C++ 復現博文,如果感興趣可以關注我。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章