#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define INSTR_NUM 320
#define INSTR_PER_PAGE 32
#define VIRTUAL_PAGES (INSTR_NUM / INSTR_PER_PAGE) // 10 pages
// 生成随机指令序列
void generate_instructions(int instr[]) {
for (int i = 0; i < INSTR_NUM; i++) {
instr
[i
] = rand() % INSTR_NUM
; // 0 ~ 319 }
}
// 指令地址转页面号
void convert_to_pages(int instr[], int pages[]) {
for (int i = 0; i < INSTR_NUM; i++) {
pages[i] = instr[i] / INSTR_PER_PAGE;
}
}
// FIFO 算法
int simulate_fifo(int pages[], int capacity) {
int faults = 0;
int frames[40];
int front = 0, rear = 0, count = 0;
int in_frame[40] = {0};
for (int i = 0; i < INSTR_NUM; i++) {
int p = pages[i];
if (!in_frame[p]) {
// 缺页
faults++;
if (count < capacity) {
frames[rear] = p;
rear = (rear + 1) % capacity;
count++;
} else {
// 淘汰最早进入的页面
int old = frames[front];
in_frame[old] = 0;
front = (front + 1) % capacity;
frames[rear] = p;
rear = (rear + 1) % capacity;
}
in_frame[p] = 1;
}
}
return faults;
}
// LRU 算法
int simulate_lru(int pages[], int capacity) {
int faults = 0;
int frames[40];
int last_used[40]; // 记录最近访问时间
for (int i = 0; i < capacity; i++) frames[i] = -1;
for (int i = 0; i < 40; i++) last_used[i] = -1;
for (int i = 0; i < INSTR_NUM; i++) {
int p = pages[i];
int hit = 0;
// 是否命中
for (int j = 0; j < capacity; j++) {
if (frames[j] == p) {
hit = 1;
break;
}
}
if (!hit) {
faults++;
// 找空位置
int placed = 0;
for (int j = 0; j < capacity; j++) {
if (frames[j] == -1) {
frames[j] = p;
placed = 1;
break;
}
}
// 若无空位,找最久未使用
if (!placed) {
int lru_page = frames[0];
int lru_index = 0;
for (int j = 1; j < capacity; j++) {
if (last_used[frames[j]] < last_used[lru_page]) {
lru_page = frames[j];
lru_index = j;
}
}
frames[lru_index] = p;
}
}
}
return faults;
}
// OPT 算法
int simulate_opt(int pages[], int capacity) {
int faults = 0;
int frames[40];
for (int i = 0; i < capacity; i++) frames[i] = -1;
for (int i = 0; i < INSTR_NUM; i++) {
int p = pages[i];
int hit = 0;
for (int j = 0; j < capacity; j++) {
if (frames[j] == p) {
hit = 1;
break;
}
}
if (!hit) {
faults++;
// 找空位
int placed = 0;
for (int j = 0; j < capacity; j++) {
if (frames[j] == -1) {
frames[j] = p;
placed = 1;
break;
}
}
if (!placed) {
int farthest_index = -1;
int replace_pos = 0;
for (int j = 0; j < capacity; j++) {
int next_use = -1;
for (int k = i + 1; k < INSTR_NUM; k++) {
if (pages[k] == frames[j]) {
next_use = k;
break;
}
}
if (next_use == -1) {
replace_pos = j; // 不再使用,直接换掉
break;
}
if (next_use > farthest_index) {
farthest_index = next_use;
replace_pos = j;
}
}
frames[replace_pos] = p;
}
}
}
return faults;
}
int main() {
int instructions[INSTR_NUM];
int pages[INSTR_NUM];
generate_instructions(instructions);
convert_to_pages(instructions, pages);
printf("内存容量\tFIFO命中率\tLRU命中率\tOPT命中率\n");
for (int cap = 4; cap <= 32; cap++) {
int fifo_fault = simulate_fifo(pages, cap);
int lru_fault = simulate_lru(pages, cap);
int opt_fault = simulate_opt(pages, cap);
double fifo_hit = 1 - fifo_fault / (double)INSTR_NUM;
double lru_hit = 1 - lru_fault / (double)INSTR_NUM;
double opt_hit = 1 - opt_fault / (double)INSTR_NUM;
printf("%3d\t\t%.4f\t\t%.4f\t\t%.4f\n", cap, fifo_hit, lru_hit, opt_hit);
}
return 0;
}