作業系統頁面置換演算法c++
作業系統頁面置換演算法
頁面置換演算法:
功能:選擇被置換的物理頁面
目標:儘可能減少頁面的調入調出次數
把未來不再訪問或者短期內不訪問的頁面調出
頁面鎖定:(以下部分)
描述必須常駐記憶體的邏輯頁面,作業系統的關鍵部分,要求響應速度的程式碼和資料,頁表中的鎖定標誌位置換演算法的評價:
記錄所有儲存單元的軌跡。模擬置換演算法,缺頁率。
區域性置換演算法:
僅限於當前程序佔用的物理頁面
最優演算法(預測未來,沒法實現):置換未來最長時間不使用的頁面,
特徵:缺頁最少,實際系統無法實現,無法預知在每隔頁面在下次訪問前的等待時間。
作為其他演算法的評價依據。
先進先出(FIFO),最近最久未使用算(過去使用,對未來的預測)法,近來與出去之間是否會被使用
時鐘演算法,最不常使用演算法
選擇在記憶體駐留時間最長的頁面進行置換
實現:維護一個記錄所有位於記憶體中的邏輯頁面連結串列
連結串列元素按駐留記憶體的時間排序,
出現缺頁時,進行鏈首去頁面置換。
特徵:
實現簡單
效能較差,調出的頁面可能是經常訪問的
程序分配物理與頁面數增加時,缺頁並不一定減少(Belady現象)
很少單獨使用
最近最久未使用演算法(LRU):統計使用時間 ——–表面優秀演算法,開銷比較大
實現:缺頁時,記錄記憶體中每個邏輯頁面的使用時間,選擇最長時間未使用的頁面進行置換。
實現演算法:
1.連結串列維護,鏈首剛剛使用的頁面,鏈尾最久未使用的頁面
2.棧維護
以下對LRU的改進:
時鐘頁面置換演算法(CLOCK):
1.對頁面的訪問情況大致訪問。
1.資料結構:在頁表中增加訪問位,描述在過去的一段時間內訪問的情況
各個頁面組織成環形連結串列
指標指向最先調入的頁面
特徵在LRU和FIFO折中。
頁面裝入記憶體時,訪問位(存在頁表項,被CPU調整)初始化為0
訪問頁面時,訪問位位置1
缺頁時,從指標當前位置順序查詢環形連結串列,訪問位為0,則置換頁面
改進的時鐘演算法:
增加修改位
最不常使用演算法:(LFU):統計使用次數
思路:缺頁時,置換訪問次數最少的頁面
實現:每個頁面增加一個訪問計數
沒有考慮程式執行的階段問題。
Belady現象:
隨著分配的物理頁面數 的增加,缺頁的次數反而升高
原因:FIFO演算法的置換特徵與程序訪問記憶體的動態特徵矛盾
被它置換出去的頁面並不一定是程序近期不會訪問的
全域性頁面置換演算法:給程序分配可變的物理頁面
置換頁面的選擇範圍是可能換出的頁面
工作集置換演算法:
程序當前正在使用的邏輯頁面集合:W(t,s)t為時間視窗的大小
常駐集:在一段時間內記憶體中的頁, 和工作集是交集,理想情況下工作集等價於常駐集,實際情況訪問的頁不再常駐集(記憶體中)。
思路:換出不再工作集的頁面 (並不一定在缺頁的時候),開銷很大
缺頁率演算法(PFF):
缺頁次數/記憶體訪問次數 或 缺頁的平均時間間隔的倒數(常使用)
影響缺頁率的因素:
頁面置換演算法、分配給程序的物理頁面數目、頁面的大小、程式的編寫方法
通過調整常駐集的大小,使得每個程序的缺頁率保持在一定範圍內
1. 如果缺頁率過高,則增加常駐集分配更多的頁面
2. 如果缺頁率過低,則減少常駐集分配更多的頁面
做法:
訪存設定引用位標誌
抖動和負載控制:
程序物理頁面太少,不能包含工作集
造成大量的缺頁,頻繁置換
程序執行速度變化
作業系統需要在併發和缺頁率之間達到一個平衡
簡單的c++實現缺頁率演算法
缺頁率置換
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<stdlib.h>
#include<string.h>
#include<set>
#include<vector>
using namespace std;
#define MEM_SIZE 10
//此處記憶體動態分配邏輯物理頁面的大小
int main()
{
int n=-1;
int t=4;
cout<<"-------------缺頁率------------"<<endl;
cout<<"請輸入程式需要的頁號:"<<endl;
//cout<<">>:輸入0 選擇缺頁率模式";
vector<int>mem;
bool find=false;
int t1=0;
int t2=-1;
set<int>myset;
while(cin>>n)
{
cout<<n<<endl;
myset.insert(n);
t2++;
find=false;
for( vector<int>::iterator i=mem.begin();i!=mem.end();i++)
{
if(n==*i)
{
cout<<"記憶體中存在:"<<n<<endl;
find =true;
}
}
if (find) continue;
int aa[MEM_SIZE];
for(int i=0;i<MEM_SIZE;i++) aa[i]=-1;
int r=0;
if((t2-t1)>t)
{
t1=t2;
for(set<int>::iterator it=myset.begin();it!=myset.end();it++)
{
aa[r]=*it;
r++;
if(r>=MEM_SIZE) r=0;
}
myset.clear();
int rr=-1;
for( vector<int>::iterator i=mem.begin();i!=mem.end();i++)
{ bool findmem=false;
rr++;
for(int j=0;j<MEM_SIZE;j++)
{
if(*i==aa[j])
{
findmem=true;
break;
}
}
if(!findmem) mem.erase(i);
}
for(int i=0;i<MEM_SIZE;i++)
{
if(mem[i]==-1)
{
mem[i]=n;
}
}
}
}
return 0;
}