C语言 时钟算法中的读取或写入总数与预期结果不匹配

rryofs0p  于 2023-10-16  发布在  其他
关注(0)|答案(1)|浏览(103)

我现在尝试用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
vdzxcuhz

vdzxcuhz1#

你的页面替换算法时钟的实现偏离了描述,因为你没有在受害者发现后提前动手。如果我们调整这个e。例如用

case clockReplace:
        while ( victim_index = clock_hand,
                clock_hand = (clock_hand + 1) % numFrames,  // always advance
                page_table[victim_index].reference_bit
              ) page_table[victim_index].reference_bit = 0;
        break;

我们得到你的 * 期望输出 *。

相关问题