1、最佳淘汰算法(OPT)
2、先進先出的算法(FIFO)
3、最近最久未使用算法(LRU)
4、簡單時鐘(鐘錶)算法(CLOCK)
命中率=1-頁面失效次數/頁地址流(序列)長度
缺頁率=缺頁次數/(缺頁次數+訪問成功次數)
1、最佳淘汰算法(Optimal)
其所選擇的被淘汰頁面將是以後永不使用的, 或許是在最長(未來)時間內不再被訪問的頁面。 採用最佳置換算法通常可保證獲得最低的缺頁率。但由千人們目前還無法預知,一個進程在內存的若干個頁面中,哪一個頁面是未來最長時間內不再被訪問的,因而該算法是無法實現的, 但可以利用該算法去評價其它算法。
舉例
假定系統爲某進程分配了三個物理塊, 並考慮有以下的頁面號引用串:
7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1
進程運行時,先將7, 0, l三個頁面裝入內存。以後,當進程要訪問頁面2時,將會產生缺頁中斷。此時OS根據最佳置換算法將選擇頁面7予以淘汰。這是因爲頁面0將作爲第5個被訪問的頁面,頁面1是第14個被訪問的頁面,而頁面7則要在第18次頁面訪問時才需調入。七次訪問頁面0時,因它已在內存而不必產生缺頁中斷。當進程訪問頁面3時,又將引起頁面l被淘汰;因爲,它在現有的1, 2, 0三個頁面中,將是以後最晚才被訪問的。 圖示採用最佳置換算法時的置換圖。由圖可看出,採用最佳置換算法發生了6次頁面置換。
代碼
#include <stdio.h>
#include<iostream>
#include <string>
#include<stdlib.h>
#include <ctype.h>
#include<algorithm>
using namespace std;
#define ERROR -1
int page[1000];//內存
int toppage;
int MAXSIZE;
int F, ch;//缺頁次數,置換次數
void watch(){//查看當前內存中存有的頁面號
printf("當前內存序列:");
for (int i = toppage; i >= 0; i--)
printf("%d ", page[i]);
//printf("\t置換次數:%d\t缺頁率:%d%%\n", ch, F * 100 / (S+F));
printf("\t置換次數:%d\t缺頁次數:%d\n", ch, F);
return;
}
int locatetime(int queue[], int num, int t, int w){//num是頁面序列總長,t是當前queue頁面序列號,w是當前內存號
for (int i = t; i <= num; i++){
if (queue[i] == page[w])return i;
}
return num + 1;
}
int Popbase(int queue[], int num, int t){//最久未使用被淘汰,t是queue序列號
int max=-1,maxid=-1,h;
for (int i = 0; i <= toppage; i++){
h=locatetime(queue, num, t,i);
if (max < h){
maxid = i;
max = h;
}
}
return maxid;
}
int search(int a){
for (int i = toppage; i >= 0; i--){
if (a == page[i]) return i;
}
return ERROR;
}
int scan(char str[], int queue[]){
int n = strlen(str), j = -1;
for (int i = 0; i < n; i++){
if (isdigit(str[i])){
sscanf(str + i, "%d", &queue[++j]);
while (isdigit(str[++i]));
i--;
}
}
return j;//總長度
}
void Optimal(){
F = 0; ch = 0;
toppage = -1;
char str[1000];//輸入字符串
int t, queue[100];//是否重新出現過,頁地址流
printf("頁地址流序列:");
scanf("%s", str);
int num = scan(str, queue)+1;//頁地址流(序列)長度(0~num,所以長度+1)
for (int i = 0; i < num; i++){
t = search(queue[i]);
if (t != ERROR){//在物理塊中
printf("不缺頁,無需置換\n");
continue;
}
else{//不在物理塊中
F++;//物理塊中無,所以缺頁次數+1
if ((toppage + 1) >= MAXSIZE){//物理塊滿,最佳置換
//最久未使用被淘汰,被淘汰位置換爲當前序列號
page[Popbase(queue, num, i)] = queue[i];//i是當前queue序列號
ch++;//置換次數+1
}
else
page[++toppage] = queue[i];
}
watch();
}
printf("頁地址流長度:%d\t命中率:%d%%\t缺頁率:%d%%\n\n", num, (num - ch) * 100 / num, F * 100 / num);
fill(page, page + num-1, 0);
}
int main(){
printf("分配給物理塊的數量:");
scanf("%d", &MAXSIZE);
while (MAXSIZE != 0){
while (MAXSIZE > 1000){
printf("分配給的物理塊過多,重新分配\n");
printf("分配給物理塊的數量:");
scanf("%d", &MAXSIZE);
}
Optimal();
printf("分配給物理塊的數量:");
scanf("%d", &MAXSIZE);
}
system("PAUSE");
return 0;
}
流程圖
2、先進先出的算法(FIFO)
其所選擇的被淘汰頁面將是以後永不使用的, 或許是在最長(未來)時間內不再被訪問的頁面。 採用最佳置換算法通常可保證獲得最低的缺頁率。但由千人們目前還無法預知,一個進程在內存的若干個頁面中,哪一個頁面是未來最長時間內不再被訪問的,因而該算法是無法實現的, 但可以利用該算法去評價其它算法。
舉例
假定系統爲某進程分配了三個物理塊, 並考慮有以下的頁面號引用串:
7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1
進程運行時,先將7, 0, l三個頁面裝入內存。以後,當進程要訪問頁面2時,將會產生缺頁中斷。此時OS根據最佳置換算法將選擇頁面7予以淘汰。這是因爲頁面0將作爲第5個被訪問的頁面,頁面1是第14個被訪問的頁面,而頁面7則要在第18次頁面訪問時才需調入。七次訪問頁面0時,因它已在內存而不必產生缺頁中斷。當進程訪問頁面3時,又將引起頁面l被淘汰;因爲,它在現有的1, 2, 0三個頁面中,將是以後最晚才被訪問的。 圖示採用最佳置換算法時的置換圖。由圖可看出,採用最佳置換算法發生了6次頁面置換。
代碼
#include <stdio.h>
#include<iostream>
#include <string>
#include<stdlib.h>
#include <ctype.h>
#include<algorithm>
using namespace std;
#define ERROR -1
int page[1000];//內存
int toppage;
int MAXSIZE;
int time;//最長駐留的page的序號
int F, ch;//缺頁次數,置換次數
void watch(){//查看當前內存中存有的頁面號
printf("當前內存序列:");
for (int i = toppage; i >= 0; i--)
printf("%d ", page[i]);
printf("\t置換次數:%d\t缺頁次數:%d\n", ch, F);
return;
}
int search(int a){
for (int i = toppage; i >= 0; i--){
if (a == page[i]) return i;
}
return ERROR;
}
int scan(char str[], int queue[]){
int n = strlen(str), j = -1;
for (int i = 0; i < n; i++){
if (isdigit(str[i])){
sscanf(str + i, "%d", &queue[++j]);
while (isdigit(str[++i]));
i--;
}
}
return j;//總長度
}
void FIFO(){
F = 0; ch = 0;
toppage = -1;
time = 0;
char str[1000];//輸入字符串
int t, queue[100];//是否重新出現過,頁地址流
printf("頁地址流序列:");
scanf("%s", str);
int num = scan(str, queue);//頁地址流(序列)長度
for (int i = 0; i <= num; i++){
t = search(queue[i]);
if (t != ERROR){//重複出現過,不缺頁
printf("不缺頁,無需置換\n");
continue;
}
else{//缺頁
F++;
if ((toppage + 1) >= MAXSIZE){//物理塊滿,最先進入的頁面出棧
page[time] = queue[i];
time = (time + 1) % MAXSIZE;
ch++;//置換次數+1
}
else//物理塊沒滿,直接置換進內存
page[++toppage] = queue[i];
watch();
}
}
num++;
printf("頁地址流長度:%d\t命中率:%d%%\t缺頁率:%d%%\n\n", num, (num - ch) * 100 / num, F * 100 / num);
fill(page, page + num-1, 0);
}
int main(){
printf("分配給物理塊的數量:");
scanf("%d", &MAXSIZE);
while (MAXSIZE != 0){
while (MAXSIZE > 1000){
printf("分配給的物理塊過多,重新分配\n");
printf("分配給物理塊的數量:");
scanf("%d", &MAXSIZE);
}
FIFO();
printf("分配給物理塊的數量:");
scanf("%d", &MAXSIZE);
}
system("PAUSE");
return 0;
}
流程圖
3、最近最久未使用算法(LRU)
最近最久未使用(LRU)的頁面置換算法是根據頁面調入內存後的使用情況做出決策的。由於無法預測各頁面將來的使用清況,只能利用 “最近的過去” 作爲 “最近的將來” 的近似, 因此,LRU置換算法是選擇最近最久未使用的頁面予以淘汰。 該算法賦予每個頁面一個訪問字段,用來記錄一個頁面自上次被訪問以來所經歷的時間t。 當需淘汰一個頁面時,選擇現有頁面中其t值最大的,即最近最久未使用的頁面予以淘汰。
舉例
當進程第一次對頁面2進行訪問時,由於頁面7是最近最久未被訪問的,故將它置換出去。當進程第一次對頁面3進行訪間時,第1頁成爲最近最久未使用的頁,將它換出。由圖可以看出, 前5個時間的圖像與最佳置換算法時的相同, 但這並非是必然的結果。 因爲最佳置換算法是從 “向後看” 的觀點出發的,即它是依據以後各頁的使用情況進行判斷;而LRU算法則是 “ 向前看” 的,即根據各頁以前的使用情況來判斷, 而頁面過去和未來的走向之間並無必然的聯繫。
代碼
#include <stdio.h>
#include<iostream>
#include <string>
#include<stdlib.h>
#include <ctype.h>
#include<algorithm>
using namespace std;
#define ERROR -1
int page[1000];//LRU棧
int toppage;
int MAXSIZE;
int F,ch;//缺頁次數,置換次數
void watch(){//查看當前內存中存有的頁面號
printf("當前內存序列:");
for (int i = toppage; i >= 0; i--)
printf("%d ", page[i]);
printf("\t置換次數:%d\t缺頁次數:%d\n",ch,F);
return;
}
void Popbase(int a){//page[a]出棧
for (int i = (a+1); i <= toppage; i++){
page[i - 1] = page[i];
}
toppage--;
return;
}
int search(int a){
for (int i = toppage; i >= 0; i--){
if (a == page[i]) return i;
}
return ERROR;
}
int scan(char str[],int queue[]){
int n = strlen(str),j=-1;
for (int i = 0; i < n; i++){
if (isdigit(str[i])){
sscanf(str + i, "%d", &queue[++j]);
while (isdigit(str[++i]));
i--;
}
}
return j;//總長度
}
void LRU(){
F = 0; ch = 0;
toppage = -1;
char str[1000];//輸入字符串
int t,queue[100];//是否重新出現過,頁地址流
printf("頁地址流序列:");
scanf("%s", str);
int num=scan(str, queue);//頁地址流(序列)長度
for(int i=0;i<=num;i++){
t = search(queue[i]);
if (t != ERROR){//重複出現過,不缺頁
Popbase(t);//重複出現的page[t]先出棧
}
else{//缺頁
F++;//缺頁次數+1
if ((toppage + 1) >= MAXSIZE){//物理塊滿,最近最久未使用的頁面出棧
Popbase(0);//最近最久未使用的頁面是page[0],出棧
ch++;//置換次數+1
}
}
page[++toppage] = queue[i];
watch();
}
num++;
printf("頁地址流長度:%d\t命中率:%d%%\t缺頁率:%d%%\n\n", num, (num - ch) * 100 / num, F * 100 / num);
fill(page, page + num - 1,0);
}
int main(){
printf("分配給物理塊的數量:");
scanf("%d", &MAXSIZE);
while (MAXSIZE != 0){
while (MAXSIZE > 1000){
printf("分配給的物理塊過多,重新分配\n");
printf("分配給物理塊的數量:");
scanf("%d", &MAXSIZE);
}
LRU();
printf("分配給物理塊的數量:");
scanf("%d", &MAXSIZE);
}
system("PAUSE");
return 0;
}
流程圖
4、簡單時鐘(鐘錶)算法(CLOCK)
我們把頁面排成一個時鐘的形狀,該時針有一個針臂。每次需要更換頁面的時候,我們從針臂所指的頁面開始 檢查。如果當前頁面的訪問位爲0,即從上次檢查到這次,若該頁面沒有被訪問過,將該頁面替換;如果當前頁面的訪問位爲1,即當前頁面被訪問過,那就將其訪問位清零,並順時針移動指針到下一個頁面。
代碼
#include <stdio.h>
#include<iostream>
#include <string>
#include<stdlib.h>
#include<ctype.h>
#include<algorithm>
using namespace std;
#define ERROR -1
typedef struct CLOCK{
int data;
bool fw;
}CLOCK;
int toppage;
int MAXSIZE;
int time;//針臂
int F, ch;//缺頁次數,置換次數
void watch(CLOCK page[]){//查看當前內存中存有的頁面號
printf("當前內存序列:");
for (int i = toppage; i >= 0; i--)
printf("%d ", page[i].data);
printf("\t置換次數:%d\t缺頁次數:%d\n", ch, F);
return;
}
int search(int a, CLOCK page[]){
for (int i = toppage; i >= 0; i--){
if (a == page[i].data) return i;
}
return ERROR;
}
int scan(char str[], int queue[]){
int n = strlen(str), j = -1;
for (int i = 0; i < n; i++){
if (isdigit(str[i])){
sscanf(str + i, "%d", &queue[++j]);
while (isdigit(str[++i]));
i--;
}
}
return j;//總長度
}
void FIFO(){
CLOCK page[1000];//內存
F = 0; ch = 0;
toppage = -1;
time = 0;//針臂指爲0
char str[1000];//輸入字符串
int t, queue[100];//是否重新出現過,頁地址流
printf("頁地址流序列:");
scanf("%s", str);
int num = scan(str, queue);//頁地址流(序列)長度
for (int i = 0; i <= num; i++){
t = search(queue[i],page);
if (t != ERROR){//重複出現過,不缺頁
printf("不缺頁,無需置換\n");
continue;
}
else{//缺頁
F++;
if ((toppage + 1) >= MAXSIZE){//物理塊滿,訪問位爲0的頁面出隊,訪問位爲1的頁面置爲0並訪問下一個直到隊尾
while (page[time].fw){//訪問位爲1的頁面都賦爲訪問位爲0直到遇到訪問位爲0的
page[time].fw = false;
time = (time+1)%MAXSIZE;
}
page[time].data = queue[i];
page[time].fw = true;//訪問位置1
time = (time + 1) % MAXSIZE;
ch++;//置換次數+1
}
else{//物理塊沒滿,直接置換進內存
toppage++;
page[toppage].data = queue[i];
page[toppage].fw = true;
}
watch(page);
}
}
num++;
printf("頁地址流長度:%d\t命中率:%d%%\t缺頁率:%d%%\n\n", num, (num - ch) * 100 / num, F * 100 / num);
}
int main(){
printf("分配給物理塊的數量:");
scanf("%d", &MAXSIZE);
while (MAXSIZE != 0){
while (MAXSIZE > 1000){
printf("分配給的物理塊過多,重新分配\n");
printf("分配給物理塊的數量:");
scanf("%d", &MAXSIZE);
}
FIFO();
printf("分配給物理塊的數量:");
scanf("%d", &MAXSIZE);
}
system("PAUSE");
return 0;
}