操作系统实验报告17:请求页面置换算法
操作系統(tǒng)實(shí)驗(yàn)報(bào)告17
實(shí)驗(yàn)內(nèi)容
- 實(shí)驗(yàn)內(nèi)容:虛擬存儲(chǔ)管理。
- 編寫(xiě)一個(gè) C 程序模擬實(shí)現(xiàn)課件 Lecture24 中的請(qǐng)求頁(yè)面置換算法
- 包括FIFO、LRU (stack and matrix implementation)、Second chance,并設(shè)計(jì)輸入用例驗(yàn)證結(jié)果。
- 編寫(xiě)一個(gè) C 程序模擬實(shí)現(xiàn)課件 Lecture24 中的請(qǐng)求頁(yè)面置換算法
實(shí)驗(yàn)環(huán)境
- 架構(gòu):Intel x86_64 (虛擬機(jī))
- 操作系統(tǒng):Ubuntu 20.04
- 匯編器:gas (GNU Assembler) in AT&T mode
- 編譯器:gcc
技術(shù)日志
實(shí)驗(yàn)內(nèi)容原理
- 頁(yè)面置換通過(guò)在內(nèi)存中找到一些實(shí)際上沒(méi)有使用的頁(yè),并將其調(diào)出置換。
- 通過(guò)修改頁(yè)面錯(cuò)誤服務(wù)例程以包括頁(yè)面替換,防止內(nèi)存過(guò)度分配。
- 使用修改位(臟位)來(lái)減少頁(yè)面?zhèn)鬏數(shù)拈_(kāi)銷(xiāo),因?yàn)橹挥行薷倪^(guò)的頁(yè)面才會(huì)寫(xiě)回磁盤(pán)。
- 頁(yè)面置換完成了邏輯內(nèi)存和物理內(nèi)存之間的分離,使得可以在較小的物理內(nèi)存上提供較大的虛擬內(nèi)存。
- 頁(yè)面置換采用以下方法。如果沒(méi)有空閑幀,那么就查找當(dāng)前不在使用的一個(gè)幀,并釋放它??梢赃@樣來(lái)釋放一個(gè)幀:將其內(nèi)容寫(xiě)到交換空間,并修改頁(yè)表(和所有其他表),以表示該頁(yè)不在內(nèi)存中?,F(xiàn)在可使用空閑幀,來(lái)保存進(jìn)程出錯(cuò)的頁(yè)面。修改缺頁(yè)錯(cuò)誤處理程序,以包括頁(yè)面置換:
- 找到所需頁(yè)面的磁盤(pán)位置。
- 找到一個(gè)空閑幀:
a. 如果有空閑幀,那么就使用它。
b. 如果沒(méi)有空閑幀,那么就使用頁(yè)面置換算法來(lái)選擇一個(gè)犧牲幀。
c. 將犧牲幀的內(nèi)容寫(xiě)到磁盤(pán)上,修改對(duì)應(yīng)的頁(yè)表和幀表。 - 將所需頁(yè)面讀入(新的)空閑幀,修改頁(yè)表和幀表。
- 從發(fā)生缺頁(yè)錯(cuò)誤位置,繼續(xù)用戶(hù)進(jìn)程。
- 請(qǐng)注意,如果沒(méi)有空閑幀,那么需要兩個(gè)頁(yè)面?zhèn)鬏?#xff08;一個(gè)調(diào)出,一個(gè)調(diào)入)。這種情況實(shí)際上加倍了缺頁(yè)錯(cuò)誤處理時(shí)間,并相應(yīng)地增加了有效訪問(wèn)時(shí)間。
- 頁(yè)面置換算法
- FIFO頁(yè)面置換
- FIFO頁(yè)面置換算法為每個(gè)頁(yè)面記錄了調(diào)到內(nèi)存的時(shí)間。當(dāng)必須置換頁(yè)面時(shí),將選擇最舊的頁(yè)面。請(qǐng)注意,并不需要記錄調(diào)入頁(yè)面的確切時(shí)間。可以創(chuàng)建一個(gè)FIFO隊(duì)列,來(lái)管理所有的內(nèi)存頁(yè)面。置換的是隊(duì)列的首個(gè)頁(yè)面。當(dāng)需要調(diào)入頁(yè)面到內(nèi)存時(shí),就將它加到隊(duì)列的尾部。
- FIFO頁(yè)面置換算法容易實(shí)現(xiàn),只需要一個(gè)在進(jìn)程的頁(yè)框架中循環(huán)的指針。
- 例子:
- Belady異常:對(duì)于有些置換算法,隨著分配幀的數(shù)量的增加,缺頁(yè)錯(cuò)誤率可能會(huì)增加。
- LRU頁(yè)面置換
- 實(shí)現(xiàn)LRU置換的一種方法是采用頁(yè)碼堆棧。每當(dāng)頁(yè)面被引用時(shí),它就從堆棧中移除并放在頂部。這樣,最近使用的頁(yè)面總是在堆棧的頂部,最近最少使用的頁(yè)面總是在底部。因?yàn)楸仨殢亩褩5闹虚g刪除條目,所以最好通過(guò)使用具有首指針和尾指針的雙向鏈表來(lái)實(shí)現(xiàn)這種方法。這樣,刪除一個(gè)頁(yè)面并放在堆棧頂部,在最壞情況下需要改變6個(gè)指針。雖說(shuō)每次更新有點(diǎn)費(fèi)時(shí),但是置換不需要搜索;指a前的堆棧b之后的堆棧針指向堆棧的底部,這是LRU頁(yè)面。這種方法特別適用于LRU置換的軟件或微代碼實(shí)現(xiàn)。
- 實(shí)現(xiàn)LRU置換的另一種方法是采用矩陣。用矩陣的方法來(lái)實(shí)現(xiàn)LRU算法的思想是使用矩陣來(lái)記錄頁(yè)面使用的頻率和時(shí)間。設(shè)矩陣是 n×n 維的,n是相關(guān)程序當(dāng)前駐內(nèi)存的頁(yè)面數(shù)。矩陣的初值為0,每次訪問(wèn)一個(gè)頁(yè)面,例如第i個(gè)虛擬頁(yè)被訪問(wèn)時(shí),可對(duì)矩陣進(jìn)行如下操作:
一是將第i行的值全部置1;
二是將第i列的值全部置一是將第i行的值全部置0;
在每次需要更換頁(yè)面時(shí),選擇矩陣?yán)飳?duì)應(yīng)行值最小的頁(yè)面。行值是指把此行所有的01代碼連起來(lái)作為二進(jìn)制的取值。 - 例子:
- 第二次機(jī)會(huì)算法
- 第二次機(jī)會(huì)置換的基本算法是一種FIFO置換算法。然而,當(dāng)選擇了一個(gè)頁(yè)面時(shí),需要檢査其引用位。如果值為0,那么就直接置換此頁(yè)面;如果引用位設(shè)置為1,那么就給此頁(yè)面第二次機(jī)會(huì),并繼續(xù)選擇下一個(gè)FIFO頁(yè)面。當(dāng)一個(gè)頁(yè)面獲得第二次機(jī)會(huì)時(shí),其引用位被清除,并且到達(dá)時(shí)間被設(shè)為當(dāng)前時(shí)間。因此,獲得第二次機(jī)會(huì)的頁(yè)面,在所有其他頁(yè)面被置換(或獲得第二次機(jī)會(huì))之前,不會(huì)被置換。此外,如果一個(gè)頁(yè)面經(jīng)常使用以致于其引用位總是得到設(shè)置,那么它就不會(huì)被置換。
- 實(shí)現(xiàn)第二次機(jī)會(huì)算法(有時(shí)稱(chēng)為時(shí)鐘算法的一種方式是采用循環(huán)隊(duì)列。指針(即時(shí)鐘指針)指示接下來(lái)要置換哪個(gè)頁(yè)面。當(dāng)需要一個(gè)幀時(shí),指針向前移動(dòng)直到找到一個(gè)引用位為0的頁(yè)面。在向前移動(dòng)時(shí),它會(huì)清除引用位。一旦找到犧牲頁(yè)面,就置換該頁(yè)面,并且在循環(huán)隊(duì)列的這個(gè)位置上插入新頁(yè)面。注意,在最壞的情況下,當(dāng)所有位都已設(shè)置,指針會(huì)循環(huán)遍歷整個(gè)隊(duì)列,給每個(gè)頁(yè)面第二次機(jī)會(huì)。在選擇下一個(gè)頁(yè)面進(jìn)行置換之前,它將清除所有引用位。如果所有位都為1,第二次機(jī)會(huì)置換退化為FIFO替換。
- 例子:
- FIFO頁(yè)面置換
設(shè)計(jì)報(bào)告
代碼設(shè)計(jì)
// page_replacement.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h>#define REFERENCE_STRING_LENGTH 20 // 引用串長(zhǎng)度 #define PAGE_SIZE 10 // 頁(yè)的大小 #define FRAME_SIZE 5 // 頁(yè)幀大小typedef struct page_node_LRU {int page_num; // 頁(yè)碼數(shù)字int page_index; // 頁(yè)在頁(yè)幀中的下標(biāo)struct page_node_LRU *pre; // 指向上一個(gè)點(diǎn)結(jié)構(gòu)的指針struct page_node_LRU *next; // 指向下一個(gè)點(diǎn)結(jié)構(gòu)的指針 } PageNode_LRU; // 用堆棧實(shí)現(xiàn)的LRU算法所使用的表示頁(yè)的點(diǎn)結(jié)構(gòu)typedef struct {PageNode_LRU *head; // 雙向鏈表表頭PageNode_LRU *tail; // 雙向鏈表表尾 } PageStack; // 用雙向鏈表實(shí)現(xiàn)的LRU算法所使用的堆棧typedef struct page_node_second_chance {int page_num; // 頁(yè)碼數(shù)字int page_index; // 頁(yè)在頁(yè)幀中的下標(biāo)int reference_bit; // 引用位struct page_node_second_chance *next; // 指向下一個(gè)點(diǎn)結(jié)構(gòu)的指針 } PageNode_Second_Chance; // 第二次機(jī)會(huì)算法所使用的表示頁(yè)的點(diǎn)結(jié)構(gòu)typedef struct {PageNode_Second_Chance *head; // 隊(duì)列隊(duì)頭PageNode_Second_Chance *clock_pointer; // 時(shí)鐘指針,指向下個(gè)犧牲幀 } PageQueue; // 第二次機(jī)會(huì)算法所使用的循環(huán)隊(duì)列// FIFO頁(yè)面置換算法使用的函數(shù) void FIFO(int *reference_string);// 用堆棧實(shí)現(xiàn)的LRU頁(yè)面置換算法使用的函數(shù) PageNode_LRU *creat_PageNode_LRU(int page_num, int page_index); void init_PageStack(PageStack *stk); void free_PageStack(PageStack *stk); void print_LRU_stack(PageStack *stack); void LRU_stack(int *reference_string);// 用矩陣實(shí)現(xiàn)的LRU頁(yè)面置換算法使用的函數(shù) void setrow1(int matrix[FRAME_SIZE][FRAME_SIZE], int row); void setcolumn0(int matrix[FRAME_SIZE][FRAME_SIZE], int column); int find_least_row(int matrix[FRAME_SIZE][FRAME_SIZE]); void print_LRU_matrix(int matrix[FRAME_SIZE][FRAME_SIZE]); void LRU_matrix(int *reference_string);// 第二次機(jī)會(huì)頁(yè)面置換算法使用的函數(shù) PageNode_Second_Chance *creat_PageNode_Second_Chance(int page_num, int page_index); void init_PageQueue(PageQueue *queue); void free_PageQueue(PageQueue *queue); void print_PageQueue(PageQueue *queue); void Second_Chance(int *reference_string);// 打印頁(yè)幀信息 void print_pageframe(int *page_frame); // 打印引用串 void print_reference_string(int *reference_string);// 打印頁(yè)幀信息 void print_pageframe(int *page_frame) {for (int i = 0; i < FRAME_SIZE; ++i) {printf("|");if (page_frame[i] != -1) {printf("%d", page_frame[i]);} else {printf(" ");}if (i == FRAME_SIZE - 1) {printf("|");}} }// FIFO頁(yè)面置換算法 void FIFO(int *reference_string) {printf("\n---------------------------------------\n");printf("page-replacement algorithm: FIFO\n\n");// 初始化頁(yè)幀中頁(yè)碼數(shù)字都為-1int page_frame[FRAME_SIZE];memset(page_frame, -1, sizeof(page_frame));int replace_index = 0;int j = 0;for (int i = 0; i < REFERENCE_STRING_LENGTH; ++i) {int page_num = reference_string[i];printf("%d: ", reference_string[i]);for (j = 0; j < FRAME_SIZE; ++j) {// 如果頁(yè)幀中已經(jīng)有要引用的頁(yè)面,那么沒(méi)有發(fā)生缺頁(yè)錯(cuò)誤,不用進(jìn)行頁(yè)面置換if (page_frame[j] == page_num) {print_pageframe(page_frame);printf(", no page fault\n");break;}}// 如果頁(yè)幀中沒(méi)有要引用的頁(yè)面,那么發(fā)生缺頁(yè)錯(cuò)誤,要進(jìn)行頁(yè)面置換if (j == FRAME_SIZE) {// 將頁(yè)幀中對(duì)應(yīng)下標(biāo)的頁(yè)碼改為要引用的頁(yè)面的頁(yè)碼page_frame[replace_index] = page_num;// 下一個(gè)犧牲幀的下標(biāo)為頁(yè)幀中的下一個(gè)循環(huán)下標(biāo)replace_index = (replace_index + 1) % FRAME_SIZE;print_pageframe(page_frame);printf(", page fault\n");}}printf("---------------------------------------\n"); }// 創(chuàng)建用堆棧實(shí)現(xiàn)的LRU算法所使用的表示頁(yè)的點(diǎn)結(jié)構(gòu) PageNode_LRU *creat_PageNode_LRU(int page_num, int page_index) {PageNode_LRU *new_node = (PageNode_LRU *)malloc(sizeof(PageNode_LRU));new_node->pre = NULL;new_node->next = NULL;new_node->page_num = page_num;new_node->page_index = page_index;return new_node; }// 初始化用雙向鏈表實(shí)現(xiàn)的LRU算法所使用的堆棧 void init_PageStack(PageStack *stk) {// 按照頁(yè)幀中下標(biāo)的對(duì)應(yīng)關(guān)系創(chuàng)建與頁(yè)幀大小相同的堆棧stk->head = creat_PageNode_LRU(-1, 0);PageNode_LRU *cur_node = stk->head;for (int i = 1; i < FRAME_SIZE; ++i) {PageNode_LRU *new_node = creat_PageNode_LRU(-1, i);cur_node->next = new_node;new_node->pre = cur_node;cur_node = new_node;}stk->tail = cur_node; }// 釋放用雙向鏈表實(shí)現(xiàn)的LRU算法所使用的堆棧的動(dòng)態(tài)內(nèi)存 void free_PageStack(PageStack *stk) {PageNode_LRU *t = stk->head;while (t != NULL) {PageNode_LRU *temp = t;t = t->next;free(temp);temp = NULL;} }// 打印用雙向鏈表實(shí)現(xiàn)的LRU算法所使用的堆棧的內(nèi)容 void print_LRU_stack(PageStack *stack) {PageNode_LRU *cur_node = stack->head;printf("LRU stack: ");while (cur_node != NULL) {printf("|");if (cur_node->page_num != -1) {printf("%d", cur_node->page_num);} else {printf(" ");}if (cur_node->next == NULL) {printf("|");}cur_node = cur_node->next;}printf("(top)\n"); }// 用堆棧實(shí)現(xiàn)的LRU算法 void LRU_stack(int *reference_string) {printf("\n------------------------------------------------------------------\n");printf("page-replacement algorithm: LRU implemented by stack\n\n");// 初始化頁(yè)幀中頁(yè)碼數(shù)字都為-1int page_frame[FRAME_SIZE];memset(page_frame, -1, sizeof(page_frame));PageStack stack;init_PageStack(&stack);for (int i = 0; i < REFERENCE_STRING_LENGTH; ++i) {int page_num = reference_string[i];printf("%d: ", reference_string[i]);PageNode_LRU *cur_node = stack.head;while (cur_node != NULL) {// 如果頁(yè)幀中已經(jīng)有要引用的頁(yè)面,那么沒(méi)有發(fā)生缺頁(yè)錯(cuò)誤,不用進(jìn)行頁(yè)面置換if (cur_node->page_num == page_num) {if (cur_node != stack.tail) {// 將這個(gè)要引用的頁(yè)面放到雙向鏈表的表尾,即堆棧的棧頂if (cur_node->pre != NULL) {cur_node->pre->next = cur_node->next;}if (cur_node->next != NULL) {cur_node->next->pre = cur_node->pre;}stack.tail->next = cur_node;cur_node->pre = stack.tail;if (cur_node == stack.head) {stack.head = cur_node->next;}cur_node->next = NULL;stack.tail = cur_node;}print_pageframe(page_frame);printf(", no page fault, ");print_LRU_stack(&stack);break;}cur_node = cur_node->next;}// 如果頁(yè)幀中沒(méi)有要引用的頁(yè)面,那么發(fā)生缺頁(yè)錯(cuò)誤,要進(jìn)行頁(yè)面置換if (cur_node == NULL) {// 將堆棧的棧底作為犧牲幀,替換新的引用頁(yè)面,并把這個(gè)頁(yè)面放到堆棧頂端PageNode_LRU *old_head = stack.head;stack.head = stack.head->next;stack.head->pre = NULL;old_head->page_num = page_num;page_frame[old_head->page_index] = page_num;stack.tail->next = old_head;old_head->pre = stack.tail;old_head->next = NULL;stack.tail = old_head;print_pageframe(page_frame);printf(", page fault, ");print_LRU_stack(&stack);}}free_PageStack(&stack);printf("------------------------------------------------------------------\n"); }// 將二維矩陣的某一行全部設(shè)置為1 void setrow1(int matrix[FRAME_SIZE][FRAME_SIZE], int row) {for (int i = 0; i < FRAME_SIZE; ++i) {matrix[row][i] = 1;} }// 將二維矩陣的某一列處與列號(hào)相等的那一行外全部設(shè)置為1 void setcolumn0(int matrix[FRAME_SIZE][FRAME_SIZE], int column) {for (int i = 0; i < FRAME_SIZE; ++i) {if (i != column) {matrix[i][column] = 0;}} }// 找到二維矩陣中1的個(gè)數(shù)最少的那一行 int find_least_row(int matrix[FRAME_SIZE][FRAME_SIZE]) {int least_one_sum = FRAME_SIZE;int least_row = 0;for (int i = 0; i < FRAME_SIZE; ++i) {int one_sum = 0;for (int j = 0; j < FRAME_SIZE; ++j) {if (matrix[i][j] == 1) {one_sum++;}}if (one_sum < least_one_sum) {least_one_sum = one_sum;least_row = i;}}return least_row; }// 打印用矩陣實(shí)現(xiàn)的LRU算法的二維矩陣 void print_LRU_matrix(int matrix[FRAME_SIZE][FRAME_SIZE]) {printf("LRU matrix:\n");for (int i = 0; i < FRAME_SIZE; ++i) {for (int j = 0; j < FRAME_SIZE; ++j) {printf("%d ", matrix[i][j]);}printf("\n");} }// 用矩陣實(shí)現(xiàn)的LRU算法 void LRU_matrix(int *reference_string) {printf("\n------------------------------------------------------------------\n");printf("page-replacement algorithm: LRU implemented by matrix\n\n");// 初始化頁(yè)幀中頁(yè)碼數(shù)字都為-1int page_frame[FRAME_SIZE];memset(page_frame, -1, sizeof(page_frame));// 初始化二維矩陣所有元素都為0int matrix[FRAME_SIZE][FRAME_SIZE];memset(matrix, 0, sizeof(matrix));for (int i = 0; i < REFERENCE_STRING_LENGTH; ++i) {int page_num = reference_string[i];printf("%d: ", reference_string[i]);int j = 0; for (j = 0; j < FRAME_SIZE; ++j) {// 如果頁(yè)幀中已經(jīng)有要引用的頁(yè)面,那么沒(méi)有發(fā)生缺頁(yè)錯(cuò)誤,不用進(jìn)行頁(yè)面置換if (page_frame[j] == page_num) {// 將引用的頁(yè)面在頁(yè)幀中的下標(biāo)的那一行的所有元素都設(shè)置為1setrow1(matrix, j);// 將引用的頁(yè)面在頁(yè)幀中的下標(biāo)的那一列的所有元素都設(shè)置為0setcolumn0(matrix, j);print_pageframe(page_frame);printf(", no page fault\n");print_LRU_matrix(matrix);break;}}// 如果頁(yè)幀中沒(méi)有要引用的頁(yè)面,那么發(fā)生缺頁(yè)錯(cuò)誤,要進(jìn)行頁(yè)面置換if (j == FRAME_SIZE) {// 找到1的個(gè)數(shù)最少的那一行,那一行的行號(hào)即為犧牲幀在頁(yè)幀中的下標(biāo)int least_one_row = find_least_row(matrix);page_frame[least_one_row] = page_num;// 將引用的頁(yè)面在頁(yè)幀中的下標(biāo)的那一行的所有元素都設(shè)置為1setrow1(matrix, least_one_row);// 將引用的頁(yè)面在頁(yè)幀中的下標(biāo)的那一列的所有元素都設(shè)置為0setcolumn0(matrix, least_one_row);print_pageframe(page_frame);printf(", page fault\n");print_LRU_matrix(matrix);}}printf("------------------------------------------------------------------\n"); }// 創(chuàng)建第二次機(jī)會(huì)頁(yè)面算法所使用的表示頁(yè)的點(diǎn)結(jié)構(gòu) PageNode_Second_Chance *creat_PageNode_Second_Chance(int page_num, int page_index) {PageNode_Second_Chance *new_node = (PageNode_Second_Chance *)malloc(sizeof(PageNode_Second_Chance));new_node->next = NULL;new_node->page_num = page_num;new_node->page_index = page_index;new_node->reference_bit = 0;return new_node; }// 初始化第二次機(jī)會(huì)算法所使用的循環(huán)隊(duì)列 void init_PageQueue(PageQueue *queue) {// 按照頁(yè)幀中下標(biāo)的對(duì)應(yīng)關(guān)系創(chuàng)建與頁(yè)幀大小相同的循環(huán)隊(duì)列queue->head = creat_PageNode_Second_Chance(-1, 0);PageNode_Second_Chance *cur_node = queue->head;for (int i = 1; i < FRAME_SIZE; ++i) {PageNode_Second_Chance *new_node = creat_PageNode_Second_Chance(-1, i);cur_node->next = new_node;cur_node = new_node;}cur_node->next = queue->head;queue->clock_pointer = queue->head; }// 釋放第二次機(jī)會(huì)算法所使用的循環(huán)隊(duì)列的動(dòng)態(tài)內(nèi)存 void free_PageQueue(PageQueue *queue) {PageNode_Second_Chance *t = queue->head;for (int i = 0; i < FRAME_SIZE; ++i) {PageNode_Second_Chance *temp = t;t = t->next;free(temp);temp = NULL;} }// 打印第二次機(jī)會(huì)算法所使用的循環(huán)隊(duì)列的內(nèi)容 void print_PageQueue(PageQueue *queue) {PageNode_Second_Chance *cur_node = queue->head;printf("page queue: ");for (int i = 0; i < FRAME_SIZE; ++i) {printf("|");if (cur_node->page_num != -1) {printf("%d", cur_node->page_num);if (cur_node->reference_bit == 1) {printf("*");}if (queue->clock_pointer == cur_node) {printf("(C)");}} else {if (queue->clock_pointer == cur_node) {printf("(C)");} else {printf(" ");}}if (i == FRAME_SIZE - 1) {printf("|");}cur_node = cur_node->next;}printf("\n"); }// 第二次機(jī)會(huì)算法 void Second_Chance(int *reference_string) {printf("\n------------------------------------------------------------------\n");printf("page-replacement algorithm: Second chance\n");printf("(\"*\" means the reference bit is 1, \"(C)\" means the clock pointer's position)\n\n");// 初始化頁(yè)幀中頁(yè)碼數(shù)字都為-1int page_frame[FRAME_SIZE];memset(page_frame, -1, sizeof(page_frame));PageQueue queue;init_PageQueue(&queue);for (int i = 0; i < REFERENCE_STRING_LENGTH; ++i) {int page_num = reference_string[i];printf("%d: ", reference_string[i]);PageNode_Second_Chance *cur_node = queue.head;for (int j = 0; j < FRAME_SIZE; ++j) {// 如果頁(yè)幀中已經(jīng)有要引用的頁(yè)面,那么沒(méi)有發(fā)生缺頁(yè)錯(cuò)誤,不用進(jìn)行頁(yè)面置換if (cur_node->page_num == page_num) {// 將這個(gè)引用的頁(yè)面的引用位設(shè)置為1cur_node->reference_bit = 1;print_pageframe(page_frame);printf(", no page fault, ");print_PageQueue(&queue); break;}cur_node = cur_node->next;}// 如果頁(yè)幀中沒(méi)有要引用的頁(yè)面,那么發(fā)生缺頁(yè)錯(cuò)誤,要進(jìn)行頁(yè)面置換if (cur_node->page_num == page_num) {continue;}// 從時(shí)鐘指針開(kāi)始,找到下一個(gè)引用位為0的頁(yè)面,作為犧牲幀while (queue.clock_pointer->reference_bit != 0) {queue.clock_pointer->reference_bit = 0;queue.clock_pointer = queue.clock_pointer->next;}// 找到引用位為0的頁(yè)面后,替換新的引用頁(yè)面page_frame[queue.clock_pointer->page_index] = page_num;queue.clock_pointer->page_num = page_num;queue.clock_pointer->reference_bit = 1;// 時(shí)鐘指針指向下一個(gè)頁(yè)面queue.clock_pointer = queue.clock_pointer->next;print_pageframe(page_frame);printf(", page fault, ");print_PageQueue(&queue);}free_PageQueue(&queue);printf("------------------------------------------------------------------\n"); }// 打印引用串 void print_reference_string(int *reference_string) {printf("reference_string:\n");for (int i = 0; i < REFERENCE_STRING_LENGTH; ++i) {printf("%d ", reference_string[i]);}printf("\n"); }int main() {int reference_string[REFERENCE_STRING_LENGTH];// 生成隨機(jī)數(shù)的方式產(chǎn)生測(cè)試樣例srand((unsigned) time(NULL));for (int i = 0; i < REFERENCE_STRING_LENGTH; ++i) {int num = rand() % PAGE_SIZE;reference_string[i] = num;}// 手動(dòng)輸入的方式產(chǎn)生測(cè)試樣例/*printf("Please input the reference string(length = %d):\n", REFERENCE_STRING_LENGTH);for (int i = 0; i < REFERENCE_STRING_LENGTH; ++i) {scanf("%d", reference_string[i]);}*/print_reference_string(reference_string);FIFO(reference_string);LRU_stack(reference_string);LRU_matrix(reference_string);Second_Chance(reference_string); }執(zhí)行命令:
gcc page_replacement.c ./a.out驗(yàn)證各個(gè)頁(yè)面置換算法的正確性
在宏定義處設(shè)置輸入的引用串的長(zhǎng)度、頁(yè)的大小、頁(yè)幀大小:
#define REFERENCE_STRING_LENGTH 20 // 引用串長(zhǎng)度 #define PAGE_SIZE 10 // 頁(yè)的大小 #define FRAME_SIZE 5 // 頁(yè)幀大小測(cè)試用例1:
#define REFERENCE_STRING_LENGTH 10 // 引用串長(zhǎng)度 #define PAGE_SIZE 5 // 頁(yè)的大小 #define FRAME_SIZE 3 // 頁(yè)幀大小3 2 0 1 2 1 2 4 1 1FIFO頁(yè)面置換算法:
可以看到,
一開(kāi)始,引用串的前三個(gè)頁(yè)碼3、2、0被放到頁(yè)幀的三個(gè)空閑幀中,按照FIFO置換,此時(shí)犧牲幀應(yīng)該為第一個(gè)幀;
下一個(gè)引用頁(yè)是1,替換第一個(gè)幀3,變成1、2、0,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀;
下一個(gè)引用頁(yè)是2,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀;
下一個(gè)引用頁(yè)是1,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀;
下一個(gè)引用頁(yè)是2,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀;
下一個(gè)引用頁(yè)是4,替換第二個(gè)幀2,變成1、4、0,下一個(gè)犧牲幀應(yīng)該為第三個(gè)幀;
下一個(gè)引用頁(yè)是1,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第三個(gè)幀;
下一個(gè)引用頁(yè)是1,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第三個(gè)幀;
過(guò)程符合FIFO頁(yè)面置換算法。
用堆棧實(shí)現(xiàn)的LRU頁(yè)面置換算法:
可以看到,
一開(kāi)始,引用串的前三個(gè)頁(yè)碼3、2、0被放到頁(yè)幀的三個(gè)空閑幀中,按照LRU算法,此時(shí)犧牲幀應(yīng)該為第一個(gè)幀;
下一個(gè)引用頁(yè)是1,替換第一個(gè)幀3,變成1、2、0,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀;
下一個(gè)引用頁(yè)是2,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第三個(gè)幀;
下一個(gè)引用頁(yè)是1,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第三個(gè)幀;
下一個(gè)引用頁(yè)是2,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第三個(gè)幀;
下一個(gè)引用頁(yè)是4,替換第三個(gè)幀0,變成1、2、4,下一個(gè)犧牲幀應(yīng)該為第一個(gè)幀;
下一個(gè)引用頁(yè)是1,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀;
下一個(gè)引用頁(yè)是1,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀;
過(guò)程符合用堆棧實(shí)現(xiàn)的LRU頁(yè)面置換算法。
用矩陣實(shí)現(xiàn)的LRU頁(yè)面置換算法:
可以看到,
一開(kāi)始,引用串的前三個(gè)頁(yè)碼3、2、0被放到頁(yè)幀的三個(gè)空閑幀中,按照LRU算法,此時(shí)犧牲幀應(yīng)該為第一個(gè)幀;
下一個(gè)引用頁(yè)是1,替換第一個(gè)幀3,變成1、2、0,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀;
下一個(gè)引用頁(yè)是2,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第三個(gè)幀;
下一個(gè)引用頁(yè)是1,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第三個(gè)幀;
下一個(gè)引用頁(yè)是2,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第三個(gè)幀;
下一個(gè)引用頁(yè)是4,替換第三個(gè)幀0,變成1、2、4,下一個(gè)犧牲幀應(yīng)該為第一個(gè)幀;
下一個(gè)引用頁(yè)是1,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀;
下一個(gè)引用頁(yè)是1,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀;
過(guò)程符合用矩陣實(shí)現(xiàn)的LRU頁(yè)面置換算法。
第二次機(jī)會(huì)頁(yè)面置換算法:
可以看到,
一開(kāi)始,引用串的前三個(gè)頁(yè)碼3、2、0被放到頁(yè)幀的三個(gè)空閑幀中,三個(gè)幀的引用位都為1。
下一個(gè)引用頁(yè)是1,時(shí)鐘指針在循環(huán)隊(duì)列中找了一輪后,將所有幀的引用位都設(shè)置為0,按照第二次機(jī)會(huì)算法,此時(shí)犧牲幀應(yīng)該為第一個(gè)幀,替換第一個(gè)幀3,變成1、2、0,第二個(gè)和第三個(gè)幀的引用位都為0,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀;
下一個(gè)引用頁(yè)是2,在頁(yè)幀中有,第二個(gè)幀的引用位被設(shè)為1,下一個(gè)犧牲幀應(yīng)該為第三個(gè)幀;
下一個(gè)引用頁(yè)是1,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第三個(gè)幀;
下一個(gè)引用頁(yè)是2,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第三個(gè)幀;
下一個(gè)引用頁(yè)是4,替換第三個(gè)幀0,變成1、2、4,第二個(gè)幀的引用位變成0,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀;
下一個(gè)引用頁(yè)是1,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀;
下一個(gè)引用頁(yè)是1,在頁(yè)幀中有,下一個(gè)犧牲幀應(yīng)該為第二個(gè)幀。
過(guò)程符合第二次機(jī)會(huì)頁(yè)面置換算法。
測(cè)試用例2:
為了方便查看,將代碼中的print_LRU_matrix()函數(shù)注釋掉,即不顯示用矩陣實(shí)現(xiàn)的LRU頁(yè)面置換算法中矩陣的變化結(jié)果,結(jié)果可對(duì)比用堆棧實(shí)現(xiàn)的LRU頁(yè)面置換算法看是否正確。
#define REFERENCE_STRING_LENGTH 20 // 引用串長(zhǎng)度 #define PAGE_SIZE 10 // 頁(yè)的大小 #define FRAME_SIZE 5 // 頁(yè)幀大小4 5 3 0 6 1 9 1 2 7 6 4 3 7 0 8 8 8 3 8執(zhí)行截圖:
分析過(guò)程見(jiàn)圖。
測(cè)試用例3:
#define REFERENCE_STRING_LENGTH 40 // 引用串長(zhǎng)度 #define PAGE_SIZE 10 // 頁(yè)的大小 #define FRAME_SIZE 5 // 頁(yè)幀大小9 5 8 2 0 1 2 4 5 1 2 8 7 6 0 9 6 9 9 6 3 4 4 4 5 7 7 0 8 4 5 7 0 6 0 2 7 2 9 3執(zhí)行截圖:
分析過(guò)程見(jiàn)圖。
總結(jié)
以上是生活随笔為你收集整理的操作系统实验报告17:请求页面置换算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 操作系统实验报告16:CPU 调度
- 下一篇: java信息管理系统总结_java实现科