题目要求:
先读懂实验文档中的两个页面置换算法,参考文档中程序,实现以下要求:
假设某个进程P有6个页面,进程访问页的顺序自拟(不少于20个),在内存中分配给该进程4个页面,编写程序,给出缺页中断次数和页面的淘汰顺序。
一、FIFO 页面置换算法
1. 程序代码(注意程序格式)
1.#include <stdio.h>
2.
3.void main(){
4. int num = 0;//缺页中断数量
5. char Y_N[26];//进程访问页有25个,Y表示产生缺页中断,N表示未产生缺页中断
6. int a[25]={ 1,2,3,4,1,
7. 2,5,1,2,3,
8. 4,5,6,1,2,
9. 4,6,3,2,5,
10. 4,6,3,2,1};//页面的调度顺序
11. int b[4][26],c[26],p = 0;//在内存中分配给该进程4个页面,b中存放3个页面的25次页面调度的页面情况。c数组中存放页面的淘汰顺序,p为c数组的指针
12. for(int i = 0; i <= 3; i++){//C语言定义数组,其初值是不确定的
13. b[i][0] = 0;
14. }
15.
16. printf(" ");
17. for(int i = 0; i < 25; i++)
18. printf("%3d",a[i]);
19. printf("\n ==========================================================================================\n");
20.
21. for(int i = 0;i < 25; i++){
22. if(a[i] == b[0][i] || a[i] == b[1][i] || a[i] == b[2][i] || a[i]==b[3][i]){
23. for(int j = 0; j <= 3; j++){
24. b[j][i + 1] = b[j][i];
25. }
26. Y_N[i] = 'N';
27. }
28. else{
29. if(i > 3){
30. c[p] = b[3][i];
31. p++;
32. }
33. b[0][i+1] = a[i];
34. for(int j = 0; j <= 2; j++){
35. b[j + 1][i + 1] = b[j][i];
36. }
37. Y_N[i]='Y';
38. num++;
39. }
40. }
41.
42.
43. for(int i = 0; i <=3; i++){
44. for(int j = 0; j < 26; j++){
45. printf("%3d", b[i][j]);
46. }
47. printf("\n ------------------------------------------------------------------------------------------\n");
48. }
49.
50. printf(" ");
51. for(int i = 0; i < 26; i++){//打印是否产生缺页中断
52. printf(" ");
53. putchar(Y_N[i]);
54. }
55.
56. printf("\n Number of page breaks: %3d\n",num);
57. printf(" Page elimination order: ");
58. for(int i = 0;i < p;i++)
59. printf("%3d",c[i]);
60. printf("\n\n");
}
2. 运行结果截图
3. 总结
在FIFO 算法的请求页式管理中,当发生缺页中断且主存没有空闲页面时,总是淘汰最先进入主存的页面,即选择在主存中驻留时间最久的页面被淘汰。
算法思路:假设进程访问页有m个,在内存中分配给该进程n个页面,开辟一个大小为m*n的数组空间,存储每次访问页的内存情况。遍历进程访问页序列,若当前页不在内存中且内存中有空闲页面(前n个进入的页),则记为缺页中断一次,并将内存中后(n-1)个页面前移一位,并将最新的页放入其中;若当前页不在内存中且内存中无空闲页面,则额外将移出的一位存至队列中;若当前页在内存中,则页面不进行移动,原样复制。
FIFO 算法是一种直观但性能较差的页面置换算法,可能会有BELADY现象,即分配的页面数增加时,缺页中断次数反而增加。
二、LRU 页面置换算法
1. 程序代码(注意程序格式)
1.#include <stdio.h>
2.
3.void max_value(int x, int cc[][2]);
4.int r_algorithm(int cc[][2]);
5.char cc[26];//进程访问页有25个
6.int max = 0;
7.
8.void main(){
9. int page, row = 0, col = 1; //b[row][col],行/列指针
10. int k = 0; //记录缺页中断次数
11. int a[25]={ 1,2,3,4,1,
12. 2,5,1,2,3,
13. 4,5,6,1,2,
14. 4,6,3,2,5,
15. 4,6,3,2,1}; //存放页的调度顺序
16. int b[4][26] = {0}; //模拟内存(分配四个页面)
17. int c[6][2] = {{1,0},{2,0},{3,0},{4,0},{5,0},{6,0}}; //定义页表并赋初值
18. int d[26], p = 0; //存放页面淘汰顺序,p页面淘汰数组 d的指针
19.
20. //*************************页面调度处理************************
21. for(int i = 0; i < 25; i++){
22. if(a[i] == b[0][i] || a[i] == b[1][i] || a[i] == b[2][i] || a[i] == b[3][i]){
23. for(int j = 0; j <= 3; j++){//将前一列数据复制到下一列
24. b[j][i + 1] = b[j][i];
25. }
26.
27. max_value(a[i],c); //将页面置为最新访问的页面
28. cc[i]='F';
29. col++;
30. }
31. else{//页面不在内存
32. if(row > 3){//内存已没有空闲页面
33. page = r_algorithm(c); //返回淘汰的页面 page
34. d[p] = page; //d[]存放被淘汰的页面
35. p++;
36. k++; //缺页中断次数
37. for(int j = 0; j <= 3; j++){//将前一列数据复制到下一列
38. b[j][i + 1] = b[j][i];
39. }
40. cc[i]='Y';
41.
42. for(int j = 0; j <= 3; j++){
43. if(b[j][i + 1] == page){
44. b[j][i + 1] = a[i];
45. break;
46. }
47. }
48. max_value(a[i],c); //将页面置为最新访问的页面
49. }
50. else{
51. for(int j = 0; j <= 3; j++){//将前一列数据复制到下一列
52. b[j][i + 1] = b[j][i];
53. }
54. cc[i]='Y';
55. k++; //缺页中断次数
56.
57. b[row][col] = a[i]; //a[i]页面进入内存
58. col++;
59. row++;
60.
61. max_value(a[i],c); //将页面置为最新访问的页面
62. }
63. }
64. }
65. //======================显示处理结果=====================
66. printf("\n ");
67. for(int i = 0; i < 25; i++)
68. printf("%3d",a[i]); //显示页面调度顺序
69. printf("\n ===============================================================================\n");
70.
71. for(int i = 0; i <= 3; i++){
72. for(int j = 0; j < 26; j++){
73. printf("%3d", b[i][j]);
74. }
75. printf("\n -------------------------------------------------------------------------------\n");
76. }
77.
78. printf(" ");
79. for(int i = 0; i < 26; i++){//打印是否产生缺页中断
80. printf(" ");
81. putchar(cc[i]);
82. }
83. printf("\n Number of page breaks: %3d",k);
84. printf("\n Page elimination order: ");
85. for(int i = 0; i < p; i++)
86. printf("%3d",d[i]); //显示页面淘汰顺序
87. printf("\n\n");
88.}
89.//============访问的页面在内存的处理(页表处理)===============
90.void max_value(int x, int c[][2]){//将页面置为最新访问的页面
91. max++;
92. for(int i = 0; i < 6; i++)
93. if(c[i][0] == x){
94. c[i][1] = max;
95. break;
96. }
97.}
98.//=============选择被淘汰的页面(页表处理)==================
99.int r_algorithm(int c[][2]){
100. int i, min, row, p;
101. for(i = 0; i < 6; i++) //查询第一个计数为非 0 的页面的计数值
102. if(c[i][1] != 0){
103. min = c[i][1];
104. p = c[i][0];
105. row = i;
106. break;
107. }
108. for(i = 0; i < 6; i++){ //寻找计数值最小的数页面
109. if(min > c[i][1] && c[i][1] != 0){
110. min = c[i][1];
111. p = c[i][0]; //最小数所对应的页号被淘汰
112. row = i; //记录最小数所在的行
113. }
114. }
115. c[row][1] = 0; //在页表中被淘汰的页面计数清零
116. return(p); //返回被淘汰的页面--P
}
2. 运行结果截图
3. 总结
在LRU 页面置换算法中,当某进程发生缺页中断且主存没有空闲页面时,选择离当前时间最近的一段时间内最久没有使用过的页被淘汰。
算法思路:
设计一种数据结构c[6][2]用于表示每个页面的调用时间。设max值为0,每进行一次页面调用,就将max的值加一并赋给当前调用的页面,此时每个页面数值的大小就代表了它们的调用时间。
遍历进程访问页序列,若当前页不在内存中且内存中有空闲页面(前n个进入的页),则记为缺页中断一次,并将前一列数据复制到下一列,然后将最新的页放入当前指针指向的内存中,并将页面置为最新访问的页面;若当前页不在内存中且内存中无空闲页面,则记为缺页中断一次,并将前一列数据复制到下一列,然后淘汰并替换数组c中对应数值最小的页面为新访问的一页,将移出的一页存至队列中,并将页面置为最新访问的页面;若当前页在内存中,则页面不进行移动,原样复制,然后将页面置为最新访问的页面。
实验中遇到的问题与解决方法:
问题1:一开始输出的模拟内存有问题,它的初始值并不为0:
解决方法:最终发现是因为存放模拟内存的数组b少申请了一个空间(要比调度的页的个数多一),将其改正后输出得以正常。
问题2:程序运行结果并不美观,虚拟机并不支持中文输出,并且代码存在着大量冗余。
解决方法:重新调整输出格式;修改精简思路:例如,将max变量修改为全局变量并赋初值0,这样一来,它的数值变化大小便可以直接反映页面调度时间,无需每次找出max的值再进行变化并赋值了。