操作系统实验-分页式存储管理

分页式存储管理

●实验目的:

  1. 熟练掌握分页式管理基本原理,并在实验过程中体现内存空间的分配与回收、地址转换过程。
  2. 掌握利用“位示图”管理内存与置换空间的分配与回收。
  3. 掌握基本的位运算。
  4. 掌握请求分页式存储管理基本原理,并在实验过程中体现内存与置换空间的分配与回收、地址转换以及缺页处理过程。

●实验内容:在实验1基础上实现分页式存储管理内存分配和地址转换过程。进一步实现请求分页式存储管理过程,包括内存和置换空间管理、地址转换以及缺页处理,能够体现FIFO和LRU算法思想。

●参考学时:6学时

●实验提示:

  1. 建立一个位示图数据结构,用来模拟内存的使用情况。位示图是利用若干位的0/1值代表某类空间的占用状态的数据结构。在本实验中,位示图的位数与设定的物理块个数相同。程序启动时可利用一组随机0或1填充位示图,以模拟程序开始执行是内存已被占用状态。

假设内存大小为64K,块大小为1K,则共有64个块,需要创建如下的位示图数据结构:

#define BLOCK_SIZE 1024 //块大小,定义成宏,便于修改

#define MEM_SIZE 64     //块个数

//定义char型数组,每个char变量占用8位,长度为8,共64位

char bitmap[MEM_SIZE/8];

随机填充的代码如下:

#include "time.h"

srand(time(NULL));

for(i=0;i<MEM_SIZE/8;i++)

…bitmap[i]=(char)rand();

随机填充后的位示图可能的值如图2-1所示。该位示图表示内存的2(0字节第2位)、3(0字节第3位)、6(0字节第6位)、8(1字节第0位)、9(1字节第1位)、12(1字节第4位)、15(1字节第7位)…等块没有被占用。

        2.在实验1基础上扩充PCB,添加进程大小和页表:

struct PCB{

int size;

int* page_table;

创建进程时输入进程大小,并根据程序中设定的页面大小为进程分配页表空间,并分配物理块。例如,在上图基础上,若要建立一个大小为5000字节的进程,则:

  1. 计算该进程共有“向上取整(5000/1024)=5”个页,需要占用5个内存块;
  2. 建立空的页表,即长度为5的一维整数数组;
  3. 从位示图中找出前5个“0”位在整个位示图中的位置号(即内存中的空闲块块号)(若第i字节第j位为0,则该位在位示图中的位置为8*i+j),并将这些位置号依次填入页表中,同时把对应的“0”改为“1”,以示对应内存块已经分配。

tmp=(struct PCB *)malloc(sizeof(struct PCB));//所创建进程的PCB

tmp->size=size;//进程大小

//计算出块个数

block_count=(int)ceil(tmp->size/(double)BLOCK_SIZE); //分配页表

tmp->page_table=(int *)malloc(sizeof(int)*block_count);

在位示图中判断某字节b的第bit_no位是1还是0代码如下:

int getbit(char b,int bit_no){  

   //将00000001左移bit_no位,得到如00010000值

   char mask=(char)1<<bit_no;

   if(b&mask) //进行与操作后结果不为0,则第bit_no位一定是1

      return 1;

   else//进行与操作后结果为0,则第bit_no位一定是0

      return 0;

}

设置位示图的某字节b的第bit_no位为1或0代码如下:

void setbit(char *b,int bit_no,int flag){

   char mask=(char)1<<bit_no;//得到如00010000值

   if(flag)//flag为真,表示将第bit_no位设置为1

      *b=*b|mask;//进行或操作,对应位变成1

   else{//flag为假,表示将第bit_no位设置为0

      mask=~mask;//取反,得到如11101111值

      *b=*b&mask;//进行与操作,对应位变成0

   }

}

  1. 输入当前执行进程所要访问的逻辑地址,并将其转换成相应的物理地址:

(1)首先编写根据页面大小得到逻辑地址中页号和页内地址分界值(如页面大小为1024,则分界值为log21024=10)

int mylog2(int size){//size为页面大小  

   return (int)ceil((log10(size)/log10(2)));

}

(2)根据输入的逻辑地址la,计算其页号和页内地址:

int la,pageno,offset,mask;

printf("逻辑地址:(<0退出)");

scanf("%d",&la);

//将逻辑地址右移若干位,得到页号

pageno=la>>mylog2(BLOCK_SIZE);

//将1111…111左移若干位,得到11…11000..00

mask=(0xffffffff)<<mylog2(BLOCK_SIZE);

//将11…11000..00取反,得到00…00111..11

mask=~mask;

//将逻辑地址与mask进行与操作,得到页内地址

offset=la&mask;

  1. 进程退出时,根据其页表内容将位示图对应位置的“1”回填为“0”。
  2. 扩充页表,将其变成支持请求和置换功能的二维页表(增加存在位等)。创建进程时可装入固定的前三页(或键盘输入初始装入页数,不同进程的装入个数可以不同),其余页装入到置换空间内(置换空间大小应为内存空间大小的1.5-2倍,对其还需建立独立的置换空间位示图)。
  3. 分别采用FIFO或LRU置换算法对地址转换过程中可能遇到的缺页现象进行页面置换。可将多次地址转换过程中所涉及到的页号视为进程的页面访问序列,从而计算置换次数和缺页率。以下是某次地址变换过程中的交互示例(红色为用户输入,蓝色为程序提示):

逻辑地址:3072

是否为写指令(Y/N):Y

逻辑地址3072对应的页号为:3,页内偏移地址为:0

3号页不在内存,外存块号为12,需置换…

   利用FIFO算法选中内存1号页,该页内存块号为6,修改位为1,外存块号为10

   将内存6号块内容写入外存10号块,成功

   将外存12号块内容调入内存6号块中,置换完毕

逻辑地址3072对应的物理地址为6144

代码

#include<iostream>
#include<string.h>
#include<queue>
#include<vector>
#include<list>
#include <array>
#include <random>
#include <algorithm>
#include <numeric>
#include<deque>

using namespace std;

int yechang, kuaichang, kuaidaxiao;
int yehao;
int kuaihao;
int fangwencishu=0, luojidizhi;

vector<int> weishitu(64, 1);
//FIOF
struct FIFO
{
    int kuaihao=-1;
    int zhuangtaiwei=0;
};
queue<int> FIOFQ;
int queyecishu = 0, zhihuancishu = 0;
int Fwulidizhi;

//LRU
struct LRU
{
    int kuaihao = -1;
    int zhuangtaiwei = 0;
};
deque<int> LRUQ;
int Lqueyecishu = 0, Lzhihuancishu = 0;
int Lwulidizhi;

void createbitmap()//创建位视图
{
    std::random_device rd;  
    std::mt19937 gen(rd()); 

    std::vector<int> indices(64);
    std::iota(indices.begin(), indices.end(), 0); 
    std::shuffle(indices.begin(), indices.end(), gen); 

    for (int i = 0; i < kuaichang; ++i) {
        weishitu[indices[i]] = 0;
    }
}

void showbitmap() {
    int flag = 0;
    for (int i = 0; i < 64; i++) {
        cout << weishitu[i] << ' ';
        flag++;
        if (flag == 8) {
            cout << endl;
            flag = 0;
        }
    }
}


int main() {
  
	cout << "输入页长 块长 块大小(kb):";
	cin >> yechang >> kuaichang >> kuaidaxiao;
    cout << "位示图" << endl;
    vector<FIFO> fifo(yechang);
    vector<LRU> lru(yechang);
    createbitmap();
    showbitmap();
    while (1) {
        cout << "输入逻辑地址:";
        cin >> luojidizhi;
        fangwencishu++;
        //页号=逻辑地址/(块大小*1024)
        yehao = luojidizhi / (kuaidaxiao * 1024);
        if (fifo[yehao].zhuangtaiwei != 1) {
            FIOFQ.push(yehao);
            queyecishu++;
            int flag = 0;
            for (int i = 0; i < 64; i++) {
                if (FIOFQ.size() > kuaichang) {
                    break;
                }
                if (weishitu[i] == 0) {
                    kuaihao = i;
                    flag = 1;//找到了
                    fifo[yehao].kuaihao = kuaihao;
                    fifo[yehao].zhuangtaiwei = 1;
                    break;
                }
            }
            if (flag == 0) {//没找到
                int tyehao = FIOFQ.front();
                FIOFQ.pop();
                fifo[yehao].kuaihao = fifo[tyehao].kuaihao;
                fifo[yehao].zhuangtaiwei = 1;
                fifo[tyehao].kuaihao = -1;
                fifo[tyehao].zhuangtaiwei = 0;
                zhihuancishu++;
            }
        }
       
        //LRU
        if (lru[yehao].zhuangtaiwei != 1) {
            LRUQ.push_back(yehao);
            Lqueyecishu++;
            int flag = 0;
            for (int i = 0; i < 64; i++) {
                if (LRUQ.size() > kuaichang) {
                    break;
                }
                if (weishitu[i] == 0) {
                    kuaihao = i;
                    weishitu[i] = 1;
                    flag = 1;//找到了
                    lru[yehao].kuaihao = kuaihao;
                    lru[yehao].zhuangtaiwei = 1;
                    break;
                }
            }
            if (flag == 0) {//没找到
                int tyehao = LRUQ.front();
                LRUQ.pop_front();
                lru[yehao].kuaihao = lru[tyehao].kuaihao;
                lru[yehao].zhuangtaiwei = 1;
                lru[tyehao].kuaihao = -1;
                lru[tyehao].zhuangtaiwei = 0;
                Lzhihuancishu++;
            }
        }
        else if(LRUQ.back()!=yehao){
           /* LRUQ.push_back(LRUQ.front());
            LRUQ.pop_front();*/

            deque<int> t;
            while (LRUQ.size()) {
                if (LRUQ.front() != yehao) {
                    t.push_back(LRUQ.front());
               }
                LRUQ.pop_front();
            }
            t.push_back(yehao);
            LRUQ = t;
        }

        cout << "位示图\n";
        showbitmap();
        cout << "FIFO:" << endl;
        //物理地址=逻辑地址%1024 + 块号*1024    块大小不是1,1024换成块大小*1024
        cout << "物理地址:" << luojidizhi % (1024 * kuaidaxiao) + kuaihao * (1024 * kuaidaxiao) << endl;
        cout << "页号  块号  状态位" << endl;
        for (int i = 0; i < yechang; i++) {
            cout << i << "     " << fifo[i].kuaihao << "     " << fifo[i].zhuangtaiwei << endl;
        }
        cout << "栈(底->顶):";
        queue<int> t = FIOFQ;
        while (t.size())
        {
            cout << t.front() << ' ';
            t.pop();
        }
        cout << endl;
        cout << "第 " << fangwencishu << " 次访问。\n";
        cout << "缺页次数:" << queyecishu << "  " << "置换次数:" << zhihuancishu << endl;
        cout << "缺页率:" << (double)queyecishu / fangwencishu * 100 << "%" << "    " << "置换率:" << (double)zhihuancishu / fangwencishu * 100 << "%" << endl;


        cout << "LRU:" << endl;
        cout << "物理地址:" << luojidizhi % (1024 * kuaidaxiao) + kuaihao * (1024 * kuaidaxiao) << endl;
        cout << "页号  块号  状态位" << endl;
        for (int i = 0; i < yechang; i++) {
            cout << i << "     " << lru[i].kuaihao << "     " << lru[i].zhuangtaiwei << endl;
        }
        cout << "栈(底->顶):";
        deque<int> tt = LRUQ;
        while (tt.size())
        {
            cout << tt.front() << ' ';
            tt.pop_front();
        }
        cout << endl;
        cout << "第 " << fangwencishu << " 次访问。\n";
        cout << "缺页次数:" << Lqueyecishu << "  " << "置换次数:" << Lzhihuancishu << endl;
        cout << "缺页率:" << (double)Lqueyecishu / fangwencishu * 100 << "%" << "    " << "置换率:" << (double)Lzhihuancishu / fangwencishu * 100 << "%" << endl;
    }


}


效果截图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值