华中科技大学操作系统实验课 实验三

一、实验目的

  • (1)理解页面淘汰算法原理,编写程序演示页面淘汰算法。
  • (2)验证Linux虚拟地址转化为物理地址的机制
  • (3)理解和验证程序运行局部性的原理。
  • (4)理解和验证缺页处理的流程。

二、实验内容

  • (1)Win/Linux编写二维数组遍历程序,理解局部性的原理。
  • (2)Windows/Linux模拟实现OPT或FIFO或LRU淘汰算法。
  • (3)研读并修改Linux内核的缺页处理函数do_no_page 或页框分配函数
    get_free_page,并用printk打印调试信息。注意:需要编译内核。建议优麒
    麟或麒麟系统。
  • (4)Linux下利用/proc/pid/pagemap技术计算某个变量或函数虚拟地址对
    应的物理地址等信息。建议优麒麟或麒麟系统。

三、实验要求

  • 第2,4必做,第1,3选做。寝室提前做完,老师机房检查和答疑。

任务2

借鉴自:操作系统 页面置换算法FIFO与LRU的实现

#define _CRT_SECURE_NO_WARNINGS


#include 
#include
#include
#include
#include 
#define Myprintf printf("|---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---|\n") //表格控制
#define bsize 4     //物理块数量
#define psize 16     //进程数量
typedef struct page {
    int num;  //记录页面号
    int time;  //记录调入内存时间
}Page;                   //页面逻辑结构,结构为方便算法实现设计

Page b[bsize];            //内存单元数 
int c[bsize][psize];   //暂保存内存当前的状态:缓冲区
int queue[100];      //记录调入队列
int K;              //调入队列计数变量 
int phb[bsize] = { 0 };   //物理块标号
int pro[psize] = { 0 };     //进程序列号
int flag[bsize] = { 0 };  //进程等待次数(存放最久未被使用的进程标志)
int i = 0, j = 0, k = 0;   //i表示进程序列号,j表示物理块号
int m = -1, n = -1;       //物理块空闲和进程是否相同判断标志
int max = -1, maxflag = 0; //标记替换物理块进程下标
int count = 0;            //统计页面缺页次数

int* build() {
    //随机产生序列号函数
    printf("随机产生一个进程序列号为:\n");
    int i = 0;
    srand(time(NULL));
    for (i = 0; i < psize; i++) {
        pro[i] = 10 * rand() / (RAND_MAX + 1) + 1;
        printf("%d  ", pro[i]);
    }
    printf("\n");
    return(pro);
}

int searchpb() {
    //查找空闲物理块
    for (j = 0; j < bsize; j++) {
        if (phb[j] == 0) {
            m = j;
            return m;
            break;
        }
    }
    return -1;
}

int searchpro() {
    //查找相同进程
    for (j = 0; j < bsize; j++) {
        if (phb[j] == pro[i]) {
            n = j;
            return j;
        }
    }
    return -1;
}

void empty() {
    //初始化内存
    for (i = 0; i < bsize; i++) {
        phb[i] = 0;
    }
    count = 0;                //计数器置零
}

void FIFO() {
    //先进先出页面置换算法
    for (i = 0; i < psize; i++) {
        m = searchpb();
        n = searchpro();
        for (j = 0; j < bsize; j++) {
            //找flag值最大的
            if (flag[j] > maxflag) {
                maxflag = flag[j];
                max = j;
            }
        }
        if (n == -1) {
            //不存在相同进程
            if (m != -1) {
                //存在空闲物理块
                phb[m] = pro[i];   //进程号填入该空闲物理块
                count++;
                flag[m] = 0;
                for (j = 0; j <= m; j++) {
                    flag[j]++;
                }
                m = -1;
            }
            else {
                //不存在空闲物理块
                phb[max] = pro[i];
                flag[max] = 0;
                for (j = 0; j < bsize; j++) {
                    flag[j]++;
                }
                max = -1;
                maxflag = 0;
                count++;
            }
        }
        else {
            //存在相同的进程
            phb[n] = pro[i];
            for (j = 0; j < bsize; j++) {
                flag[j]++;
            }
            n = -1;
        }
        for (j = 0; j < bsize; j++) {
            printf("%d  ", phb[j]);
        }
        printf("\n");
    }
    printf("缺页次数为:%d\n", count);
    printf("\n");
}

void Init(Page* b, int c[bsize][psize]) {
    //初始化内存单元、缓冲区
    int i, j;
    for (i = 0; i < psize; i++) {
        b[i].num = -1;
        b[i].time = psize - i - 1;
    }
    for (i = 0; i < bsize; i++)
        for (j = 0; j < psize; j++)
            c[i][j] = -1;
}

//取得在内存中停留最久的页面,默认状态下为最早调入的页面
int GetMax(Page* b) {
    int i;
    int max = -1;
    int tag = 0;
    for (i = 0; i < bsize; i++) {
        if (b[i].time > max) {
            max = b[i].time;
            tag = i;
        }
    }
    return tag;
}

//判断页面是否已在内存中
int Equation(int fold, Page* b) {
    int i;
    for (i = 0; i < bsize; i++) {
        if (fold == b[i].num)
            return i;
    }
    return -1;
}

//LRU核心部分
void Lruu(int fold, Page* b) {
    int i;
    int val;
    val = Equation(fold, b);
    if (val >= 0) {
        b[val].time = 0;
        for (i = 0; i < bsize; i++)
            if (i != val)
                b[i].time++;
    }
    else {
        queue[++K] = fold; //记录调入页面
        val = GetMax(b);
        b[val].num = fold;
        b[val].time = 0;
        for (i = 0; i < bsize; i++)
            if (i != val)
                b[i].time++;
    }
}

void LRU() {
    int i, j;
    K = -1;
    Init(b, c);
    for (i = 0; i < psize; i++) {
        Lruu(pro[i], b);
        //c[0][i] = pro[i];??
        //记录当前的内存单元中的页面
        for (j = 0; j < bsize; j++)
            c[j][i] = b[j].num;
    }
    //结果输出 
    printf("内存状态为:\n");
    Myprintf;
    for (j = 0; j < psize; j++)
        printf("|%2d ", pro[j]);
    printf("|\n");
    Myprintf;
    for (i = 0; i < bsize; i++) {
        for (j = 0; j < psize; j++) {
            if (c[i][j] == -1)
                printf("|%2c ", 32);
            else
                printf("|%2d ", c[i][j]);
        }
        printf("|\n");
    }
    Myprintf;
    printf("\n调入队列为:");
    for (i = 0; i < K + 1; i++)
        printf("%3d", queue[i]);
    printf("\n缺页次数为:%6d\n缺页率:%16.6f", K + 1, (float)(K + 1) / psize);
}

struct Node {
    int position;
    Node* next;
};

struct Head {
    int thread = -1;
    Head* next = NULL;
    Node* position = NULL;
}head;

void init(int thread,int position) {
    Head* h = &head;
    while (1) {
        if (h->thread == thread) {//找到线程
            Node* n = h->position;
            while (n->next!=NULL) {
                n = n->next;
            }
            Node* newn = new Node();
            n->next = newn;
            newn->position = position;
            newn->next = NULL;
            //printf("找到线程%d\n", thread);
            return;
        }
        else if(h->next==NULL){//未找到线程
            Head *newh = new Head();
            h->next = newh;

            newh->thread = thread;
            newh->next = NULL;
            newh->position = new Node();
            newh->position->next = NULL;
            newh->position->position = position;
            //printf("未找到线程%d\n",thread);
            return;
        }
        else {//去找下一个线程
            h = h->next;
        }
    }
}

int get(int thread) {//检测进程是否在内存块
    for (int i = 0; i < bsize; ++i) {
        if (b[i].num == thread)return i;
    }
    return -1;
}

int search(int thread,int i) {
    Head* h = &head;
    while(h->next!=NULL) {
        if (h->thread == thread) {
            Node* n = h->position;
            while(n!=NULL){
                if (n->position > i)return n->position;
                else if (n->next == NULL)return psize+1;
                else n = n->next;
            }
        }
        else {
            h = h->next;
        }
    }
    return -1;
}

int Maxc(int x[bsize]) {
    int max1,max2,max;
    if (x[0] >= x[1])max1 = 0;
    else max1 = 1;
    if (x[2] >= x[3])max2 = 2;
    else max2 = 3;
    if (x[max1] >= x[max2])max = max1;
    else max = max2;
    return max;
}

void OPT() {
    //Init(b, c);
    for (int i = 0; i < psize; ++i) {//预先初始化未来进程
        init(pro[i], i);
    }
    for (int i = 0; i < bsize; ++i) {//初始化物理块设置
        b[i].num=-1;
    }
    printf("初始化正常\n");
    for (int i = 0; i < psize; i++) {//载入进程
        int c = get(pro[i]);
        if (c == -1) {//不在进程块内
            //printf("%d不在进程块内\n", pro[i]);
            int nextTh[bsize];
            for (int j = 0; j < bsize; ++j) {
                if (b[j].num == -1)nextTh[j] = psize+5;
                else nextTh[j] = search(b[j].num,i);
                //printf("nextTh[%d]=%d\t", j, nextTh[j]);
            }
            int maxc = Maxc(nextTh);
            //printf("%d为置换块\n",maxc);
            b[maxc].num = pro[i];
            count++;
        }
        for (int i = 0; i < bsize; ++i) {
            printf("%d\t", b[i].num);
        }
        printf("\n");
    }
    printf("缺页次数为:%d\n", count);
    printf("\n");
}

int main()
{
    int sel;
    do {
        printf("0、退出(Exit)\n");
        printf("1、产生随机序列\n");
        printf("2、最久未使用(LRU)\n");
        printf("3、先进先出(FIFO)\n");
        printf("4、最佳置换方法(OPT)\n");
        printf("<请选择所要执行的操作:(0)(1)(2)(3)(4)>\n");
        scanf("%d", &sel);
        if (sel == 0) {
            printf("退出 \n");
        }
        if (sel == 1) {
            build();
        }
        if (sel == 2) {
            printf("LRU\n");
            LRU();
            empty();
            printf("\n");
        }
        if (sel == 3) {
            printf("FIFO\n");
            FIFO();
            empty();
            printf("\n");
        }
        if (sel == 4) {
            printf("OPT");
            OPT();
            empty();
            printf("\n");
        }
    } while (sel != 0);
}

任务4

HUST_CSE_OS_EXPERIMENT_3|第7章 内存管理

在这里插入图片描述

你可能感兴趣的:(操作系统,操作系统,实验作业)