(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]中的某条指令处,其序号为; ④顺序执行下一条指令,即序号为+1; ⑤通过随机数,跳转到后地址部分[+2,319]中的某条指令处,其序号为; ⑥顺序执行下一条指令,即序号为+1; ⑦重复跳转到前地址部分、顺序执行、跳转到后地址部分、顺序执行的过程,直至320条指令执行完。
时间: 2024-03-19 08:44:44 浏览: 164
为了模拟作业的执行过程,我们可以使用一个数组来保存作业的所有指令,另外再定义一个长度为4的数组来模拟内存中的页面。具体的C语言实现如下:
```c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define PAGE_SIZE 10 // 页面大小
#define PAGE_NUM 32 // 页面数
#define MEM_SIZE 4 // 内存大小
int job[PAGE_SIZE * PAGE_NUM]; // 作业的所有指令
int memory[MEM_SIZE]; // 内存中的页面
int page_fault = 0; // 缺页次数
// 初始化作业指令
void init_job() {
int i;
for (i = 0; i < PAGE_SIZE * PAGE_NUM; i++) {
job[i] = i;
}
}
// 获取指令对应的页面号
int get_page_num(int instruction) {
return instruction / PAGE_SIZE;
}
// 判断页面是否在内存中
int is_page_in_memory(int page_num) {
int i;
for (i = 0; i < MEM_SIZE; i++) {
if (memory[i] == page_num) {
return 1;
}
}
return 0;
}
// 获取被置换页面的下标
int get_replace_index(int* used) {
int i, index = 0;
for (i = 1; i < MEM_SIZE; i++) {
if (used[i] < used[index]) {
index = i;
}
}
return index;
}
// 置换页面,使用OPT算法
void replace_page_opt(int* used, int* next_use) {
int i, j, max_gap = -1, index = 0;
for (i = 0; i < MEM_SIZE; i++) {
int gap = PAGE_SIZE;
for (j = 0; j < PAGE_SIZE * PAGE_NUM; j++) {
if (job[j] == memory[i]) {
if (next_use[j] > i) {
gap = next_use[j] - i;
}
break;
}
}
if (gap > max_gap) {
max_gap = gap;
index = i;
}
}
memory[index] = job[next_use[memory[index]]];
}
// 置换页面,使用FIFO算法
void replace_page_fifo(int* used, int* next_use) {
int index = 0, i;
for (i = 1; i < MEM_SIZE; i++) {
if (next_use[memory[i]] < next_use[memory[index]]) {
index = i;
}
}
memory[index] = job[next_use[memory[index]]];
}
// 置换页面,使用LRU算法
void replace_page_lru(int* used, int* next_use) {
int index = get_replace_index(used);
memory[index] = job[next_use[memory[index]]];
}
// 执行作业中的指令
void run_job() {
int i, j = 0;
int used[MEM_SIZE] = {0};
int next_use[PAGE_SIZE * PAGE_NUM] = {0};
for (i = 0; i < PAGE_SIZE * PAGE_NUM; i++) {
next_use[i] = PAGE_SIZE * PAGE_NUM;
}
// 50%的指令是顺序执行的
for (i = 0; i < PAGE_SIZE * PAGE_NUM / 2; i++) {
int page_num = get_page_num(job[j]);
if (is_page_in_memory(page_num)) {
printf("物理地址:%d\n", j % PAGE_SIZE + memory[page_num] * PAGE_SIZE);
} else {
printf("发生缺页\n");
page_fault++;
if (j < MEM_SIZE) {
memory[j] = page_num;
} else {
int k;
for (k = 0; k < MEM_SIZE; k++) {
if (!is_page_in_memory(page_num)) {
memory[k] = page_num;
break;
}
}
if (k == MEM_SIZE) {
// 需要进行页面置换
if (i % 3 == 0) {
replace_page_opt(used, next_use);
} else if (i % 3 == 1) {
replace_page_fifo(used, next_use);
} else {
replace_page_lru(used, next_use);
}
}
}
}
used[j % MEM_SIZE] = i;
next_use[j] = i + 1;
j++;
}
// 25%的指令是均匀分布在前地址部分
for (i = 0; i < PAGE_SIZE * PAGE_NUM / 4; i++) {
int k = rand() % j;
int page_num = get_page_num(job[k]);
if (is_page_in_memory(page_num)) {
printf("物理地址:%d\n", k % PAGE_SIZE + memory[page_num] * PAGE_SIZE);
} else {
printf("发生缺页\n");
page_fault++;
if (j < MEM_SIZE) {
memory[j] = page_num;
} else {
int k;
for (k = 0; k < MEM_SIZE; k++) {
if (!is_page_in_memory(page_num)) {
memory[k] = page_num;
break;
}
}
if (k == MEM_SIZE) {
// 需要进行页面置换
if (i % 3 == 0) {
replace_page_opt(used, next_use);
} else if (i % 3 == 1) {
replace_page_fifo(used, next_use);
} else {
replace_page_lru(used, next_use);
}
}
}
}
used[j % MEM_SIZE] = i;
next_use[k] = i + 1;
j++;
}
// 25%的指令是均匀分布在后地址部分
for (i = 0; i < PAGE_SIZE * PAGE_NUM / 4; i++) {
int k = rand() % (PAGE_SIZE * PAGE_NUM - j) + j;
int page_num = get_page_num(job[k]);
if (is_page_in_memory(page_num)) {
printf("物理地址:%d\n", k % PAGE_SIZE + memory[page_num] * PAGE_SIZE);
} else {
printf("发生缺页\n");
page_fault++;
if (j < MEM_SIZE) {
memory[j] = page_num;
} else {
int k;
for (k = 0; k < MEM_SIZE; k++) {
if (!is_page_in_memory(page_num)) {
memory[k] = page_num;
break;
}
}
if (k == MEM_SIZE) {
// 需要进行页面置换
if (i % 3 == 0) {
replace_page_opt(used, next_use);
} else if (i % 3 == 1) {
replace_page_fifo(used, next_use);
} else {
replace_page_lru(used, next_use);
}
}
}
}
used[j % MEM_SIZE] = i;
next_use[k] = i + 1;
j++;
}
}
int main() {
srand(time(NULL));
init_job();
run_job();
printf("缺页率:%f\n", (float)page_fault / (PAGE_SIZE * PAGE_NUM));
return 0;
}
```
在上面的代码中,我们使用了三种页面置换算法:OPT(最佳置换)、FIFO(先进先出)和LRU(最近最少使用)。三种算法的实现都在 `replace_page_opt`、`replace_page_fifo` 和 `replace_page_lru` 函数中。其中,`used` 数组记录了每个页面最后一次被使用的时间戳,`next_use` 数组记录了每个指令下一次被使用的时间戳,用于计算页面的使用距离。在实现过程中,我们还使用了 `rand()` 函数来随机生成跳转到前地址部分和后地址部分的指令。
最后,我们在 `main` 函数中调用 `init_job()` 和 `run_job()` 函数来执行作业,并计算缺页率。注意,缺页率的计算方法是缺页次数除以总指令数。
阅读全文