当前位置:   article > 正文

操作系统实验:页面置换算法——FIFO、LRU 代码实现_页面置换算法代码

页面置换算法代码

FIFO(First-In-First-Out)

        最简单的页面置换算法是FIFO。在分配内存页面数(AP)小于进程页面数(PP)时,最先运行的AP个页面放入内存;当内存分配页面被占满时,如果又需要处理新的页面,则将原来放的内存中的AP个页中最先进入的调出(FIFO),再将新页面放入;所使用的内存页面构成一个队列。

实验要求:

1)初始化。设置两个数组page[ap]pagecontrol[pp]分别表示进程页面数和内存分配的页面数,并产生一个随机数序列main[total_instruction](这个序列由page[ap]的下标随机构成)表示待处理的进程页面顺序,diseffect0

2)看main[]中是否有下一个元素,若有,就由main[]中获取该页面下标,并转(3),如果没有则转(7)。

3)如果该页已在内存中,就转(2),否则转(4),同时未命中的diseffect1

4)观察pagecontrol是否占满,如果占满则须将使用队列(在第(6)步中建立的)中最先进入的(就是队列的第一个单元)pagecontrol单元“清干净”,同时将page[]单元置为“不在内存中”。

5) 将该page[]pagecontrol[]建立对应关系(可以改变pagecontrol[]的标志位,也可以采用指针链接,总之至少要使对应的pagecontrol单元包含两个信息:一是它被使用了,二是哪个page[]单元使用的。page[]单元也包含两个信息:对应的pagecontrol单元号和本page[]单元已在内存中)。

 (6) 将用到的pagecontrol置入使用队列(这里的队列是一种FIFO的数据结构),返回(2)。

(7) 显示计算1-diseffect / total_instruction*100%,完成。

程序框图: 

 

代码实现: 

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<time.h>
  4. #define ProcessPageNum 10 //进程页面数
  5. #define MemPageNum 5 //内存页面数
  6. #define totalInstruction 100 //引用次数
  7. int diseffect = 0; //缺页错误数
  8. /*定义进程页面结构体*/
  9. struct pageNode{
  10. int pageID; //进程页面ID
  11. int flag; //1表示页面在内存中,0表示不在
  12. int pagecontrolIndex; //所在内存页面ID 不在内存中时值为-1
  13. };
  14. /*定义内存页面结点*/
  15. struct pagecontrolNode{
  16. int pagecontrolID; //内存页面ID
  17. int flag; //1表示被占用,0表示空闲
  18. int pageIndex; //所加载进程页面ID
  19. struct pagecontrolNode *next;
  20. };
  21. /*定义FIFO队列*/
  22. struct pagecontrolQueue{
  23. struct pagecontrolNode *front;
  24. struct pagecontrolNode *rear;
  25. };
  26. /*返回队首结点*/
  27. struct pagecontrolNode* getFront(struct pagecontrolQueue *queue){
  28. return queue->front;
  29. }
  30. /*入队*/
  31. void inQueue(struct pagecontrolQueue *queue,struct pagecontrolNode *p){
  32. if(queue->front == NULL){
  33. queue->front = p;
  34. queue->rear = p;
  35. }else{
  36. queue->rear->next = p;
  37. queue->rear = p;
  38. queue->rear->next = NULL;
  39. }
  40. }
  41. /*出队*/
  42. void outQueue(struct pagecontrolQueue *queue){
  43. if(queue->front == NULL) exit(-1);
  44. else{
  45. queue->front = queue->front->next;
  46. if(queue->front == NULL) queue->rear = NULL;
  47. }
  48. }
  49. /*判断内存页面是否被占满 1为满*/
  50. int isFull(struct pagecontrolNode *pagecontrol[MemPageNum]){
  51. int i = 0;
  52. for (i;i < MemPageNum;i++){
  53. if(pagecontrol[i]->flag == 0) return 0;
  54. }
  55. return 1;
  56. }
  57. /*初始化page数组*/
  58. void initPage(struct pageNode *page[ProcessPageNum]){
  59. int i = 0;
  60. for(i;i < ProcessPageNum;i++){
  61. page[i] = (struct pageNode*)malloc(sizeof(struct pageNode));
  62. page[i]->flag = 0;
  63. page[i]->pageID = i;
  64. page[i]->pagecontrolIndex = -1;
  65. }
  66. }
  67. /*初始化pagecontrol数组*/
  68. void initPagecontrol(struct pagecontrolNode *pagecontrol[MemPageNum]){
  69. int i = 0;
  70. for(i;i < MemPageNum;i++){
  71. pagecontrol[i] = (struct pagecontrolNode*)malloc(sizeof(struct pagecontrolNode));
  72. pagecontrol[i]->pagecontrolID = i;
  73. pagecontrol[i]->flag = 0;
  74. pagecontrol[i]->pageIndex = -1;
  75. pagecontrol[i]->next = NULL;
  76. }
  77. }
  78. int main(){
  79. struct pageNode *page[ProcessPageNum];
  80. struct pagecontrolNode *pagecontrol[MemPageNum];
  81. initPage(page);
  82. initPagecontrol(pagecontrol);
  83. /*初始化队列*/
  84. struct pagecontrolQueue *queue;
  85. queue = (struct pagecontrolQueue*)malloc(sizeof(struct pagecontrolQueue));
  86. queue->front = NULL;
  87. queue->rear = NULL;
  88. /*构造随机序列buffer*/
  89. int buffer[totalInstruction];
  90. int i = 0;
  91. srand((unsigned)time(NULL));
  92. for(i;i < totalInstruction;i++){
  93. buffer[i] = rand() % ProcessPageNum;
  94. }
  95. int j = 0;
  96. int index = 0; //当前内存页面下标
  97. for(j;j < totalInstruction;j++){
  98. if(page[buffer[j]]->flag == 0){ //若当前页面不在内存中
  99. diseffect++; //缺页错误数加1
  100. page[buffer[j]]->flag = 1;
  101. if(isFull(pagecontrol)){ //若内存已满,则需要页面置换
  102. page[queue->front->pageIndex]->flag = 0; //队首页面被换出
  103. page[queue->front->pageIndex]->pagecontrolIndex = -1;
  104. queue->front->pageIndex = page[buffer[j]]->pageID; //存入当前页面
  105. struct pagecontrolNode *temp;
  106. temp = getFront(queue);
  107. outQueue(queue); //队首页面出队列
  108. inQueue(queue,temp); //修改后再加入队列
  109. }else{ //如果内存未满,则按照先后顺序存入
  110. pagecontrol[index]->flag = 1;
  111. pagecontrol[index]->pageIndex = page[buffer[j]]->pageID;
  112. page[buffer[j]]->pagecontrolIndex = pagecontrol[index]->pagecontrolID;
  113. inQueue(queue, pagecontrol[index]);
  114. index++;
  115. }
  116. }
  117. }
  118. double rightRate = (1.0 - ((double)diseffect / (double)totalInstruction))*100;
  119. printf("错误次数%d\n",diseffect);
  120. printf("正确率%.2f%%\n",rightRate);
  121. }

LRU(Least-Recent-Used algorithm)

        计数器实现法:在最简单的情况下,为每个页表条目关联一个使用时间域,并为CPU添加一个逻辑时钟或计数器。每次内存引用都会递增时钟;且每当进行页面引用时,时钟寄存器的内容会复制到相应页面的页表条目的使用时间域。这样我们总是找到每个页面最后被引用的时间,便可以置换拥有最小使用时间的页面。

实验要求:

(1) 初始化。设置两个数组page[ap]pagecontrol[pp]分别表示进程页面数和内存分配的页面数,并产生一个随机数序列main[total_instruction](这个序列由page[ap]的下标随机构成)表示待处理的进程页面顺序,diseffect0

(2) 看序列main[]中是否有下一个元素,如果有,就由main[]中获取该页面下标,并转(3),如果没有则转(6)。

(3) 如果该page[]单元在内存中便改变页面属性,使它保留“最近使用”的信息,转(2),否则转(4),同时diseffect1

(4) 看是否有空闲页面,如果有,就返回页面指针,并转到(5),否则,在内存页面d其“清干净”,并返回该页面指针。

(5) 在需处理的page[]与(4)中得到的pagecontrol[]之间建立联系,同时让对应的page[]单元保存“最新使用”的信息,转(2)。

         (6) 如果序列处理完成,就输出计算1-diseffect / total_instruction*100%的结果

程序框图: 

 

 代码实现:

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<time.h>
  4. /*实现方法与FIFO算法大同小异,无需定义队列,而是用计数器实现选择牺牲帧*/
  5. #define ProcessPageNum 10 //进程页面数
  6. #define MemPageNum 5 //内存页面数
  7. #define totalInstruction 100 //引用次数
  8. int diseffect = 0; //缺页错误数
  9. /*定义进程页面结构体*/
  10. struct pageNode{
  11. int pageID; //进程页面ID
  12. int flag; //1表示页面在内存中,0表示不在
  13. int pagecontrolIndex; //所在内存页面ID 不在内存中时值为-1
  14. int useTime; //最后被引用时间
  15. };
  16. /*定义内存页面结点*/
  17. struct pagecontrolNode{
  18. int pagecontrolID; //内存页面ID
  19. int flag; //1表示被占用,0表示空闲
  20. int pageIndex; //所加载进程页面ID
  21. };
  22. /*初始化page数组*/
  23. void initPage(struct pageNode *page[ProcessPageNum]){
  24. int i = 0;
  25. for(i;i < ProcessPageNum;i++){
  26. page[i] = (struct pageNode*)malloc(sizeof(struct pageNode));
  27. page[i]->flag = 0;
  28. page[i]->pageID = i;
  29. page[i]->pagecontrolIndex = -1;
  30. page[i]->useTime = 0;
  31. }
  32. }
  33. /*初始化pagecontrol数组*/
  34. void initPagecontrol(struct pagecontrolNode *pagecontrol[MemPageNum]){
  35. int i = 0;
  36. for(i;i < MemPageNum;i++){
  37. pagecontrol[i] = (struct pagecontrolNode*)malloc(sizeof(struct pagecontrolNode));
  38. pagecontrol[i]->pagecontrolID = i;
  39. pagecontrol[i]->flag = 0;
  40. pagecontrol[i]->pageIndex = -1;
  41. }
  42. }
  43. /*判断内存页面是否被占满 1为满*/
  44. int isFull(struct pagecontrolNode *pagecontrol[MemPageNum]){
  45. int i = 0;
  46. for (i;i < MemPageNum;i++){
  47. if(pagecontrol[i]->flag == 0) return 0;
  48. }
  49. return 1;
  50. }
  51. /*找到内存中页面最后引用时间最小的page结点并返回*/
  52. struct pageNode* findMinUseTime(struct pageNode *page[ProcessPageNum]){
  53. struct pageNode *temp;
  54. temp = (struct pageNode*)malloc(sizeof(struct pageNode));
  55. temp->useTime = totalInstruction;
  56. int i = 0;
  57. for(i;i < ProcessPageNum;i++){
  58. if(page[i]->useTime < temp->useTime && page[i]->flag == 1){
  59. temp = page[i];
  60. }
  61. }
  62. return temp;
  63. }
  64. int main(){
  65. struct pageNode *page[ProcessPageNum];
  66. struct pagecontrolNode *pagecontrol[MemPageNum];
  67. initPage(page);
  68. initPagecontrol(pagecontrol);
  69. /*构造随机序列buffer*/
  70. int buffer[totalInstruction];
  71. int i = 0;
  72. srand((unsigned)time(NULL));
  73. for(i;i < totalInstruction;i++){
  74. buffer[i] = rand() % ProcessPageNum;
  75. }
  76. int j = 0;
  77. int timer = 0; //设置计数器
  78. int index = 0; //当前内存页面下标
  79. for(j;j < totalInstruction;j++){
  80. timer++; //计数器递增
  81. page[buffer[j]]->useTime = timer;
  82. if(page[buffer[j]]->flag == 0){ //若当前页面不在内存中
  83. diseffect++; //缺页错误数加1
  84. page[buffer[j]]->flag = 1;
  85. if(isFull(pagecontrol)){ //若内存已满
  86. struct pageNode *temp = findMinUseTime(page); //找到将被置换的页面
  87. temp->flag = 0;
  88. temp->useTime = 0;
  89. pagecontrol[temp->pagecontrolIndex]->pageIndex = page[buffer[j]]->pageID; //修改pagecontrol数组
  90. page[buffer[j]]->pagecontrolIndex = pagecontrol[temp->pagecontrolIndex]->pagecontrolID; //修改page数组
  91. temp->pagecontrolIndex = -1;
  92. }else{ //若内存未满,则按顺序存入
  93. pagecontrol[index]->flag = 1;
  94. pagecontrol[index]->pageIndex = page[buffer[j]]->pageID;
  95. page[buffer[j]]->pagecontrolIndex = pagecontrol[index]->pagecontrolID;
  96. index++;
  97. }
  98. }
  99. }
  100. double rightRate = (1.0 - ((double)diseffect / (double)totalInstruction))*100;
  101. printf("错误次数%d\n",diseffect);
  102. printf("正确率%.2f%%\n",rightRate);
  103. }

参考资料:

《操作系统概念(第九版)》

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/163598
推荐阅读
相关标签
  

闽ICP备14008679号