1、实验目的
通过对页面、页表、地址转换和页面置换过程的模拟,加深对请求调页系统的原理和实现过程的理解。
2、实验内容
(1)假设每个页面中可存放10条指令,分配给一作业的内存块数为4。
(2)用C语言模拟一作业的执行过程。该作业共有320条指令,即它的地址空间为32页,目前它的所有页都还未调入内存。在模拟过程中,如果所访问的指令已经在内存中,则显示其物理地址,并转下一条指令。如果所访问的指令还未装入内存,则发生缺页,此时需记录缺页的次数,并将相应页调入内存。如果4个内存块中均已装入该作业,则需进行页面置换。最后显示其物理地址,并转下一条指令。在所有320条指令执行完毕后,请计算并显示作业运行过程中发生的缺页率。
(3)置换算法:请分别考虑OPT、FIFO和LRU算法。
(4)作业中指令的访问次序按下述原则生成:
•50%的指令是顺序执行的。
•25%的指令是均匀分布在前地址部分。
•25%的指令时均匀分布在后地址部分。
具体的实施办法是:
- 在[0,319]之间随机选取一条起始执行指令,其序号为m;
- 顺序执行下一条指令,即序号为m+1的指令;
- 通过随机数,跳转到前地址部分[0,m-1]中的某条指令处,其序号为m1;
- 顺序执行下一条指令,即序号为m1+1的指令;
- 通过随机数,跳转到后地址部分[m1+2,319]中的某条指令处,其序号为m2;
- 顺序执行下一条指令,即序号为m2+1的指令;
- 重复跳转到前地址部分、顺序执行、跳转到后地址部分、顺序执行的过程,直至执行320条指令。
核心代码
/*通过随机数产生一个指令序列,共320条指令*/
void produce_inst()
{
int m, n;
int num = 0;
while(num < maxn)
{
m = rand() % maxn;
inst[num++] = m % maxn;
if(num == maxn) break;
inst[num++] = m + 1;
if(num == maxn) break;
int tmp = rand() % m;
inst[num++] = tmp;
if(num == maxn) break;
inst[num++] = tmp + 1;
if(num == maxn) break;
tmp = rand();
tmp = tmp % (318 - m);
inst[num++] = tmp;
if(num == maxn) break;
inst[num++] = tmp + 1;
if(num == maxn) break;
}
}
void FIFO_solve()
{
memset(in, false, sizeof(in));
int fault_n = 0; // 缺页率
int ptr, i;
// 预调页填满空间
ptr = 0; // 下一个要放的位置
for (i = 0; i < maxn && ptr < size; i++) {
if (!in[page[i]]) {
pin[ptr++] = page[i];
in[page[i]] = true;
fault_n++;
}
}
// 继续执行剩下的指令
ptr = 0; // 队列里最先进来的位置,即下一个要被替换的位置
for (; i < maxn; i++) {
if (!in[page[i]]) {
// 请补全该部分
in[pin[ptr]] = false;
pin[ptr] = page[i];
in[page[i]] = true;
ptr++;
fault_n++;
ptr = ptr % size;
}
}
printf("\nBy FIFO algorithm, the fault-page number is: %d\n", fault_n);
printf(" the hit ratio is : %.2lf\n", (1 - (fault_n + 0.0) / 320.0));
}
void LRU_solve()
{
int ltu[maxp]; // last_time_use
int ti = 1; // 模拟时间
int fault_n = 0;
memset(ltu, 0, sizeof(ltu));
memset(in, false, sizeof(in));
memset(pin, -1, sizeof(pin));
int min, ptr, i, j;
for (i = 0; i < maxn; i++) {
if (!in[page[i]]) {
// 寻找lru
min = 1000000;
ptr = 0;
for (j = 0; j < size; j++) {
if (ltu[j] < min) {
// 请补全该部分
min = ltu[j];
ptr = j;
}
}
// 替换或写入
if (pin[ptr]!= -1) {
in[pin[ptr]] = false;
}
// 请补全该部分
in[page[i]] = true;
pin[ptr] = page[i];
fault_n++;
ltu[ptr] = ti++;
}
else { // 已经在内存里则只需更改最近使用时间
for (j = 0; j < size; j++) {
if (pin[j] == page[i]) {
ltu[j] = ti++;
break;
}
}
}
}
printf("\nBy LRU algorithm, the fault-page number is: %d\n", fault_n);
printf(" the hit ratio is : %.2lf\n", (1 - (fault_n + 0.0) / 320.0));
}
void OPT_solve()
{
int ntu[maxp]; // next_time_use
int fault_n = 0;
int i, j;
memset(in, false, sizeof(in));
memset(ntu, -1, sizeof(ntu));
// 预调页填满
int ptr = 0;
for (i = 0; i < maxn && fault_n < size; i++) {
if (!in[page[i]]) {
in[page[i]] = true;
pin[ptr] = page[i];
fault_n++;
ptr++;
}
}
// 初始化ntu数组
ptr = 0;
for (j = i; j < maxn && ptr < 32; j++) {
if (ntu[page[j]] == -1) {
// 请补全该部分
ntu[page[j]] = j;
ptr++;
}
}
int max;
for (; i < maxn; i++) {
if (!in[page[i]]) {
max = 0;
ptr = 0;
for (j = 0; j < size; j++) {
if (ntu[pin[j]] == -1) {
ptr = j;
break;
}
if (ntu[pin[j]] > max) {
// 请补全该部分
max = ntu[pin[j]];
ptr = j;
}
}
in[pin[ptr]] = false;
in[page[i]] = true;
pin[ptr] = page[i];
fault_n++;
}
ntu[page[i]] = -1;
for (j = i + 1; j < maxn; j++) {
if (page[j] == page[i]) {
ntu[page[i]] = j;
break;
}
}
}
printf("\nBy OPT algorithm, the fault-page number is: %d\n", fault_n);
printf(" the hit ratio is : %.2lf\n", (1 - (fault_n + 0.0) / 320.0));