【操作系统】页面置换算法
頁面置換算法
在進程運行過程中,若需要訪問的物理塊不在內存中,就需要通過一定的方式來將頁面載入內存,而此時內存很可能已無空閑空間,因此就需要一定的算法來選擇內存中要被置換的頁面,這種算法就被稱為頁面置換算法。頁面置換算法的好壞,將直接影響系統的性能。
一個好的頁面置換算法,應做到減少頁面置換的頻率。盡量將以后不會用到的或較長時間不會使用的頁面給置換出。
下面介紹幾種常用的頁面置換算法。
1. 最佳置換算法
該算法是一種理想化的算法,具有非常好的性能,但是由于目前無法預知未來,因此難以實現。
該算法選擇淘汰的頁面是:未來永遠不會再使用的頁面 or 未來最長時間不再被訪問的頁面。該算法保證了可以獲得最低缺頁率,但無法預知未來頁面的使用情況,因此目前無法實現,但通常用來評價其他算法。
例:假定系統為某進程分配了三個物理塊,并考慮有以下的頁面號引用串:
7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1
進程運行時,先將 7,0,1 三個頁面裝入內存。以后,當進程要訪問頁面 2 時,將會產生缺頁中斷。此時 OS 根據最佳置換算法,將選擇頁面 7 予以淘汰。這是因為頁面 0 將作為第 5 個被訪問的頁面,頁面 1 是第 14 個被訪問的頁面,而頁面 7 則要在第 18 次頁面訪問時才需調入。下次訪問頁面 0 時,因它已在內存而不必產生缺頁中斷。當進程訪問頁面 3時,又將引起頁面 1 被淘汰;因為,它在現有的 1,2,0 三個頁面中,將是以后最晚才被訪問的。圖 4-26 示出了采用最佳置換算法時的置換圖。由圖可看出,采用最佳置換算法發生了 6 次頁面置換。
2. 先進先出(FIFO)頁面置換算法
該算法總是淘汰最先進入內存的頁面,即選擇在內存中駐留時間最久的頁面予以淘汰。
例:同上。當進程第一次訪問頁面 2 時,將把第 7 頁換出,因為它是最先被調入內存的;在第一次訪問頁面 3 時,又將把第 0 頁換出, 因為它在現有的 2, 0, 1 三個頁面中是最老的頁。 由圖 4-27 可以看出,利用 FIFO 算法時進行了 12 次頁面置換,比最佳置換算法正好多一倍。
3. 最近最久未使用(LRU)算法
該算法以過去預測未來,選擇之前最長時間未使用的頁面置換。但是由于利用“過去”作為“未來”的近似這一做法并非完全可靠,因此有時會造成缺頁率非常高,導致效率會非常低。
例:同上。當進程第一次對頁面 2 進行訪問時,由于頁面 7 是最近最久未被訪問的,故將它置換出去。當進程第一次對頁面 3進行訪問時,第 1 頁成為最近最久未使用的頁,將它換出。由圖可以看出,前 5 個時間的圖像與最佳置換算法時的相同,但這并非是必然的結果。因為,最佳置換算法是從“向后看”的觀點出發的,即它是依據以后各頁的使用情況;而 LRU 算法則“向前看”的,即根據各頁以前的使用情況來判斷,而頁面過去和未來的走向之間并無必然的聯系。
4. 代碼實現
該部分代碼使用vector來實現,未使用鏈表。
/*************************************************************************> 測試數據> 20> 7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1> 3************************************************************************/#include <iostream> #include <algorithm> #include <vector> #include <map> using namespace std;class PageReplacement { private:vector<int> page;int page_num; //物理內存塊數 public:PageReplacement() : page_num(0) {}void create();void print();void physical_block_print( const vector<int>& );bool isfind( const vector<int>&, int ); //查找是否已在內存物理塊中void FIFO(); //FIFO頁面置換算法void LRU(); //LRU頁面置換算法void OPT(); //OPT頁面置換算法 };void PageReplacement::create() {cout << "請輸入頁面個數: ";int n, t;cin >> n;cout << "請輸入頁面串:\n";while( n-- ) {cin >> t;page.push_back( t );}cout << "請輸入內存物理塊數: ";cin >> page_num; }void PageReplacement::print() {int n = page.size();cout << "頁面串:\n";for( int i = 0; i < n; i++ ) {cout << page[i] << ' ';}cout << endl; }void PageReplacement::physical_block_print( const vector<int>& t ) {int n = t.size();for( int i = 0; i < n; i++ ) {cout << t[i] << ' ';}cout << endl; }bool PageReplacement::isfind( const vector<int> & block, int t ) {if ( find( block.begin(), block.end(), t ) != block.end() ) {return true;}return false; }/* FIFO頁面置換算法 */ void PageReplacement::FIFO() {vector<int> physical_block( page_num, -1 );int n = page.size(), cur = 0;int not_found = 0;cout << "FIFO頁面置換情況:\n";for( int i = 0; i < n; i++ ) {if( !isfind( physical_block, page[i] ) ) {physical_block[cur] = page[i]; //頁面置換cur = (cur+1)%page_num;not_found++;}physical_block_print( physical_block ); //輸出每個物理塊信息}cout << "缺頁次數:"<< not_found << endl; }/* LRU頁面置換算法 */ void PageReplacement::LRU() {vector<int> physical_block( page_num, -1 );map<int, int> page_time;int n = page.size();int not_found = 0;for( int i = 0; i < n; i++ ) {if ( !isfind( physical_block, page[i] ) ) { //當前頁不在為物理塊中if ( page_time.size() < page_num ) { //物理塊未放滿physical_block[i] = page[i];page_time[page[i]] = i;} else { //物理塊放滿,進行頁面置換map<int, int>::iterator it = page_time.begin(), t = it;for( it++; it != page_time.end(); it++ ) {if ( t->second > it->second ) {t = it;}}int index;for( index = 0; index < page_num && physical_block[index]!=t->first; index++ );physical_block[index] = page[i];page_time.erase( t );page_time[page[i]] = i;}not_found++;} else { //在物理塊中,更新頁面最后使用時間page_time[page[i]] = i;}physical_block_print( physical_block );}cout << "缺頁次數:"<< not_found << endl; }/* OPT頁面置換算法 */ void PageReplacement::OPT() {vector<int> physical_block( page_num, -1 );int n = page.size();int not_found = 0;for( int i = 0; i < n; i++ ) {if( !isfind( physical_block, page[i] ) ) { //當前頁不在物理塊中if( i < page_num ) { //物理塊未放滿physical_block[i] = page[i];} else { //物理塊放滿,進行頁面置換map<int, int> page_time;int k, j;/* 獲取物理塊中頁面此后的最先使用時間 */for( j = 0; j < page_num; j++ ) { //遍歷physical_blockfor( k = i+1; k < n; k++ ) { //遍歷pageif( physical_block[j] == page[k] ) {page_time[page[k]] = k;break;}}if( k == n ) {page_time[physical_block[j]] = k;}}/* 尋找可以置換的頁面 */map<int, int>::iterator it = page_time.begin(), t = it;for( ; it != page_time.end(); it++ ) {if ( t->second < it->second ) {t = it;}}/* 獲取被置換頁面在物理塊的下標 */int index = 0;for( ; index < page_num && physical_block[index] != t->first; index++ );physical_block[index] = page[i];}not_found++;}physical_block_print( physical_block );}cout << "缺頁次數:"<< not_found << endl; }int main() {PageReplacement t;t.create();// t.FIFO();t.LRU();// t.OPT();return 0; }總結
以上是生活随笔為你收集整理的【操作系统】页面置换算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 四海流云剧情介绍
- 下一篇: 【操作系统】哲学家就餐问题