西南交通大学【操作系统实验5】

实验目的

  1. (1)了解内存管理的概念,掌握分页、分段操作过程。
  2. (2)掌握虚拟内存技术的概念,重点理解替换策略。
  3. (3)理解选择替换页算法OPT、FIFO、LRU、CLOCK。

实验内容

(用户态)在Linux下编程实现虚存页面替换算法的模拟程序。

实验环境

Ubuntu 12.04 LTS

Device name: oslinux-virtual-machine

Memory: 1001.2MiB

Processor: AMD Ryzen 77730U with Radeon Graphics

Graphics: Unknown

OS type: 32-bit

Disk: 20.3GB

实验步骤

  1. (1)根据用户输入参数,包含进程大小(页数),进程地址(页地址)顺        序,驻留集大小。
  2. (2)验证test5.c中FIFO、LRU替换算法。
  3. (3)新建工程replace,编写并运行CLOCK和OPT算法。

5.实验结果

对test5.c中FIFO、LRU替换算法的验证

可以看到,当使用的是FIFO算法时,当第一次page fault时,将page1换出,并换入page2;当第二次page fault时,将page4换出,并换入page1;当第三次page fault时,将page0换出,并换入page4;当第四次page fault时,将page2换出,并换入page3 。由此可见,总是最先进入的页被换出,符合FIFO先进先出算法。

可以看到,当使用LRU算法时,每当遇到page fault时,总是保留之前最近几次访问过的几个page,并将驻留集中最久没有访问过的page换出,然后换入当前需要的page,符合LRU算法。

CLOCK和OPT算法运行结果

核心代码

#include <stdio.h>

#include <stdlib.h>

#include <time.h>



#define random(x) (rand() % x)

#define MULTIPLE 3



typedef struct page_s //页的数据结构

{

    int n; // number

    int v; // visit flag

} page;



char *menu[] = {

    "c - CLOCK",

    "o - OPT",

    "q - QUIT",

    NULL};



int getchoice(char *greet, char *choices[]) //实现菜单选择功能

{

    int chosen = 0;

    int selected;

    char **option;



    do

    {

        printf("Choice: %s\n", greet);

        option = choices;

        while (*option)

        {

            printf("%s\n", *option);

            option++;

        }

        do

        {

            selected = getchar();

        } while (selected == '\n');

        option = choices;

        while (*option)

        {

            if (selected == *option[0])

            {

                chosen = 1;

                break;

            }

            option++;

        }

        if (!chosen)

        {

            printf("Incorrect choice, select again\n");

        }

    } while (!chosen);

    return selected;

}



void buildPageReference(int size, page **reference, page *program)

{

    int i;

    int n;

    printf("Page reference : ");

    for (i = 0; i < size; i++)

    {

        n = random(size / MULTIPLE);

        reference[i] = &program[n]; //随机取一个进程的页放进预分配数组中

        program[n].n = n;

        program[n].v = 0;

        printf("| %d ", n);

    }

    printf("\n");

}



void print(int n, page *frame, int size)

{

    int i;



    printf("no. %d step: ", n);

    for (i = 0; i < size; i++)

    {

        printf("| %d ", frame[i].n);

    }

    printf("\n");

}



int Search(int n, page *list, int size)

{

    int i;

    for (i = 0; i < size; i++)

    {

        if (list[i].n == n)

            return i;

    }

    return -1;

}



int findNext(int n, page **list, int start, int size)

{

    int count = size;

    int i;

    for (i = start; i < size; i++)

    {

        if (list[i]->n == n)

            break;

        else

            count++;

    }

    return count;

}



int findLastMax(page *frame, int size)

{

    int tmp = 0, s, i, j = 0;

    for (i = 0; i < size; i++)

    {

        s = frame[i].v;

        if (s > tmp)

        {

            tmp = s;

            j = i;

        }

    }

    return j;

}



int findLastMin(page *frame, int size)

{

    int tmp = frame[0].v, s, i, j = 0;

    // printf("| %d ", tmp);

    for (i = 1; i < size; i++)

    {

        s = frame[i].v;

        // printf("| %d ", s);

        if (s < tmp)

        {

            tmp = s;

            j = i;

        }

    }

    // printf("\n");

    return j;

}



void opt(int fsize, page *frame, int rsize, page **pageR)

{

    int i, j, p = 0, q;

    int f = 0; //记录page fault,缺页中断

    for (i = 0; i < fsize; i++)

    {

        frame[i].n = -1;

        frame[i].v = 0;

    }

    for (i = 0; i < rsize; i++)

    {

        q = Search(pageR[i]->n, frame, fsize);

        if (q != -1) //三段式,先判断是否已经有这个页,有直接访问,若无再判断是否有新页框,若都没有再开始本算法

            ;

        else if (i < fsize || p < fsize)

        {

            frame[p].n = pageR[i]->n; //有未使用的页框,直接访问

            p++;

        }

        else

        {

            for (j = 0; j < fsize; j++)

            {

                frame[j].v = findNext(frame[j].n, pageR, i, rsize); //迭代更新v值,即计算下次找到该页时的间距

            }

            q = findLastMax(frame, fsize); //普通的顺序查找算法,找出最长的间隔时间的页框(用v值比较)

            frame[q].n = pageR[i]->n;

            f++;

        }

        print(i, frame, fsize);

    }

    printf("page fault : %d\n", f);

}



void clk(int fsize, page *frame, int rsize, page **pageR)

{

    int i, j = 0, p = 0,q;

    int f = 0; //记录page fault,缺页中断

    for (i = 0; i < fsize; i++)

    {

        frame[i].n = -1;

        frame[i].v = 0;

    }

    for (i = 0; i < rsize; i++)

    {

        if (q = Search(pageR[i]->n, frame, fsize) != -1) //三段式,先判断是否已经有这个页,有直接访问,若无再判断是否有新页框,若都没有再开始本算法

            frame[q].v = 1;

        else if (i < fsize || p < fsize)

        {

            frame[p].n = pageR[i]->n;

            frame[p].v = 1;

            j++;

            p++;

        }

        else

        {

            while (1)

            {

                if (frame[j % fsize].v == 0) //类似于FIFO,但是多了1位v,用于在触发缺页中断时标记该页框是否已被访问过

                {

                    frame[j % fsize].n = pageR[i]->n;

                    frame[j % fsize].v = 1;

                    j++; // j维护循环队列指向

                    f++;

                    break;

                }

                else

                {

                    frame[j % fsize].v = 0;

                    j++; // j维护循环队列指向

                }

            }

        }

        print(i, frame, fsize);

    }

    printf("page fault : %d\n", f);

}



int main()

{

    int choice = 0;

    int logSize; //逻辑内存大小

    int phySize; //物理内存大小(实际的页框)

    page *program;

    page **pageR;

    page *frame;

    int prSize;



    srand((int)time(0));

    printf("Enter number of pages in program: ");

    scanf("%d", &logSize);



    printf("Enter number of frames in physical memory: ");

    scanf("%d", &phySize);



    program = (page *)malloc(sizeof(int) * 2 * logSize);

    frame = (page *)malloc(sizeof(int) * 2 * phySize);



    prSize = logSize * MULTIPLE;                     //预分配逻辑内存大小

    pageR = (page **)malloc(sizeof(int *) * prSize); //预分配逻辑内存

    buildPageReference(prSize, pageR, program);      //初始化预分配逻辑内存的数组



    do

    {

        choice = getchoice("Please select an action", menu);

        printf("You have chosen: %c\n", choice);

        switch (choice)

        {

        case 'o':

            opt(phySize, frame, prSize, pageR);

            break;

        case 'c':

            clk(phySize, frame, prSize, pageR);

            break;

        default:

            break;

        }

    } while (choice != 'q');

    exit(0);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

还有糕手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值