我现在尝试用C写一个虚拟内存模拟器来实现页面替换。当我测试时钟算法时,我发现我的结果与预期的结果不一致。
这是我的初始代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
int pageNo;
int modified;
int reference_bit; // use for the clock algorithm
} page;
enum repl { randomReplace, fifoReplace, lruReplace, clockReplace};
int createMMU(int);
int checkInMemory(int);
int allocateFrame(int);
page selectVictim(int, enum repl);
const int pageoffset = 12; /* Page size is fixed to 4 KB */
int numFrames;
page *page_table; // create a page table for three replacement algorithms
unsigned long *timeStamps; // create a time stamp for the lru algorithm
unsigned long global_timeStamp = 0; // global time stamp for the lru algorithm
unsigned long *load_timeStamps; // create a time stamp for the fifo algorithm
int clock_hand = 0; // clock hand for the clock algorithm
/* Creates the page table structure to record memory allocation */
int createMMU(int frames)
{
// to do
numFrames = frames; // set the number of frames
page_table = (page *)malloc(sizeof(page) * frames); // allocate memory for the page table
timeStamps = (unsigned long *)malloc(sizeof(unsigned long) * frames); // allocate memory for the time stamp
load_timeStamps = (unsigned long *)malloc(sizeof(unsigned long) * frames); // allocate memory for the load time stamp
// check if the memory allocation is successful
if (page_table == NULL || timeStamps == NULL || load_timeStamps == NULL) {
free(page_table);
free(timeStamps);
free(load_timeStamps);
return -1;
}
// initialize the page table
for (int i = 0; i < frames; i++) {
page_table[i].pageNo = -1;
page_table[i].modified = 0;
page_table[i].reference_bit = 0;
timeStamps[i] = 0;
load_timeStamps[i] = 0;
}
return 0;
}
/* Checks for residency: returns frame no or -1 if not found */
int checkInMemory(int page_number)
{
int result = -1;
// to do
for (int i = 0; i < numFrames; i++) {
if (page_table[i].pageNo == page_number) {
result = i;
// Update the time stamp for this page as it is being accessed.
timeStamps[i] = global_timeStamp;
global_timeStamp++;
break;
}
}
return result;
}
/* allocate page to the next free frame and record where it put it */
int allocateFrame(int page_number)
{
// to do
for (int i = 0; i < numFrames; i++) {
if (page_table[i].pageNo == -1) {
page_table[i].pageNo = page_number;
page_table[i].modified = 0;
page_table[i].reference_bit = 0;
timeStamps[i] = global_timeStamp;
load_timeStamps[i] = global_timeStamp;
global_timeStamp++;
return i;
}
}
return -1;
}
/* Selects a victim for eviction/discard according to the replacement algorithm, returns chosen frame_no */
page selectVictim(int page_number, enum repl mode)
{
page victim;
// to do
int victim_index = 0;
switch (mode) {
// randomly select a victim page
case randomReplace:
victim_index = rand() % numFrames;
break;
// select the first page in the page table as the victim page
case fifoReplace:
victim_index = 0;
for (int i = 0; i < numFrames; i++) {
if (load_timeStamps[i] < load_timeStamps[victim_index]) {
victim_index = i;
}
}
break;
// select the page with the smallest time stamp as the victim page
case lruReplace:
victim_index = 0;
for (int i = 0; i < numFrames; i++) {
if (timeStamps[i] < timeStamps[victim_index]) {
victim_index = i;
}
}
break;
// select the first page with reference bit 0 as the victim page
case clockReplace:
while (1) {
if (page_table[clock_hand].reference_bit == 0) {
victim_index = clock_hand;
break;
}
}
break;
default:
break;
}
victim = page_table[victim_index]; // get the victim page
page_table[victim_index].pageNo = page_number; // replace the victim page with the new page
page_table[victim_index].modified = 0; // reset the modified bit
page_table[victim_index].reference_bit = 0; // reset the reference bit
timeStamps[victim_index] = global_timeStamp; // update the time stamp
global_timeStamp++; // update the global time stamp
return victim; // return the victim page
}
这是我的初始代码现在我对结果的差异感到困惑。为什么我的测试数据与预期输出不匹配?
在查找数据后,我认为可能是无限循环的问题,所以我在case clockreplace
中添加了一个新代码,但这并没有解决问题。
case clockReplace:
while (1) {
if (page_table[clock_hand].reference_bit == 0) {
victim_index = clock_hand;
break;
} else {
page_table[clock_hand].reference_bit = 0;
clock_hand = (clock_hand + 1) % numFrames;
}
}
break;
下面是main
函数:
int main(int argc, char *argv[])
{
char *tracename;
int page_number, frame_no, done;
int do_line;
// int i;
int no_events, disk_writes, disk_reads;
int debugmode;
enum repl replace;
int allocated = 0;
// int victim_page;
unsigned address;
char rw;
page Pvictim;
FILE *trace;
printf("argc: %d\n", argc);
for(int i = 0; i < argc; i++) {
printf("argv[%d]: %s\n", i, argv[i]);
}
if (argc < 5) {
printf("Usage: ./memsim inputfile numberframes replacementmode debugmode \n");
exit(-1);
} else {
tracename = argv[1];
trace = fopen(tracename, "r");
if (trace == NULL) {
printf("Cannot open trace file %s\n", tracename);
exit( -1);
}
numFrames = atoi(argv[2]);
if (numFrames < 1) {
printf( "Frame number must be at least 1\n");
exit( -1);
}
if (strcmp(argv[3], "lru\0") == 0)
replace = lruReplace;
else
if (strcmp(argv[3], "rand\0") == 0)
replace = randomReplace;
else
if (strcmp(argv[3], "clock\0") == 0)
replace = clockReplace;
else
if (strcmp(argv[3], "fifo\0") == 0)
replace = fifoReplace;
else {
printf("Replacement algorithm must be rand/fifo/lru/clock \n");
exit(-1);
}
if (strcmp(argv[4], "quiet\0") == 0)
debugmode = 0;
else
if (strcmp(argv[4], "debug\0") == 0)
debugmode = 1;
else {
printf("Replacement algorithm must be quiet/debug \n");
exit(-1);
}
}
done = createMMU(numFrames);
if (done == -1) {
printf("Cannot create MMU");
exit(-1);
}
no_events = 0;
disk_writes = 0;
disk_reads = 0;
do_line = fscanf(trace, "%x %c", &address, &rw);
while (do_line == 2) {
page_number = address >> pageoffset;
frame_no = checkInMemory(page_number); /* ask for physical address */
if (frame_no == -1) {
disk_reads++ ; /* Page fault, need to load it into memory */
if (debugmode) printf("Page fault %8d \n", page_number);
if (allocated < numFrames) { /* allocate it to an empty frame */
frame_no = allocateFrame(page_number);
allocated++;
} else {
Pvictim = selectVictim(page_number, replace); /* returns page number of the victim */
frame_no = checkInMemory(page_number); /* find out the frame the new page is in */
if (Pvictim.modified) { /* need to know victim page and modified */
disk_writes++;
if (debugmode) printf("Disk write %8d \n", Pvictim.pageNo);
} else
if (debugmode) printf("Discard %8d \n", Pvictim.pageNo);
}
}
if (rw == 'R') {
page_table[frame_no].reference_bit = 1; // Mark the page as recently referenced
if (debugmode) printf( "reading %8d \n", page_number);
} else
if (rw == 'W') {
page_table[frame_no].modified = 1; // Mark the page as modified
// mark page in page table as written - modified
if (debugmode) printf("writting %8d \n", page_number);
} else {
printf("Badly formatted file. Error on line %d\n", no_events + 1);
exit(-1);
}
no_events++;
do_line = fscanf(trace, "%x %c", &address, &rw);
}
printf("total memory frames: %d\n", numFrames);
printf("events in trace: %d\n", no_events);
printf("total disk reads: %d\n", disk_reads);
printf("total disk writes: %d\n", disk_writes);
printf("page fault rate: %.4f\n", (float)disk_reads / no_events);
// free the allocated memory
free(page_table);
free(timeStamps);
free(load_timeStamps);
return 0;
}
但效果并不好,
这是我的输入:
gcc -o memsim memsim.c
./memsim trace1 4 clock quiet
这是我的输出:
total memory frames: 4
events in trace: 12
total disk reads: 8
total disk writes: 3
page fault rate: 0.6667
这是预期输出:
total memory frames: 4
events in trace: 12
total disk reads: 9
total disk writes: 3
page fault rate: 0.7500
这是一个名为trace1的测试数据文件:
0000000 W
0001000 R
0002000 R
0003000 R
0002000 W
0004000 R
0003008 R
0003008 W
0000004 R
0001004 R
0005008 R
0002004 R
1条答案
按热度按时间vdzxcuhz1#
你的页面替换算法时钟的实现偏离了描述,因为你没有在受害者发现后提前动手。如果我们调整这个e。例如用
我们得到你的 * 期望输出 *。