• 存储管理实验


    一、实验目的 

         连续内存分配方式会形成许多“碎片”,虽然可以通过“紧凑”方法将许多碎片拼接成可用的大块空间,但须为之付出很大开销。如果允许将一个进程直接分散地装入到许多不相邻接的分区中,则无需再进行“紧凑”。基于这一思想而产生了离散分配方式。

    如果离散分配的基本单位是页,则称为分页存储管理方式;如果离散分配的基本单位是段,则称为分段存储管理方式。  

    在分页存储管理方式中,如果不具备页面兑换功能,则称为基本的分页存储管理方式,或称为纯分页存储管理方式,它不具备支持虚拟存储器的功能,它要求把每个作业全部装入内存后方能运行。

    本实验通过程序模拟操作系统的基本分页存储管理方式,进一步理解这一内存分配方式的原理和特点,加深对理论知识的掌握。 

    二、实验要求 

     1、用C语言或Java语言编写程序模拟操作系统对内存的基本分页存储管理方式  

    2、程序要能正确对“内存”进行“分配”和“回收”,能接受用户的输入,显示内存的分配情况,并有一定的容错能力。  

    3、每个人独立按时完成实验内容。 

    三、实验方法

    #include<iostream>
    #include<iostream.h>
    #include<iomanip.h>
    #include<ctype.h>
    #define N 6
    #define M 4
    struct{
        int lnumber;
        int flag;
        int pnumber;
        int write;
        int dnumber;
    }page[N];
    
    int p[M];
    int head;
    void initial(void);
    intdo_mmap(int);
    void do_page_fault(int);
    void run_first_instructon(int);
    void run_a_instruction(int);
    void print_page_and_fifoqueue(void);
    main()
    {
        int laddress,paddress;
        int lnumber,ad,pnumber;
        print_page_and_fifoqueue();
        run_first_instructon(0x0000);
        cout<<"输入下一条指令的逻辑地址(0~32767)(-1 to end)"<<endl; 
        cin>>laddress;
        while(laddress>32767){
             cout<<"输入错误! 请重新输入下一条指令的逻辑地址(0~32767)(-1 to end)"<<endl; 
             cin>>laddress; 
        }
        while(laddress!=-1){ 
               lnumber=laddress>>10; 
                lnumber 
              if(page[lnumber].flag==1){ 
                  paddress=do_mmap(laddress); 
              cout<<paddress<<"输出转换后的物理地址"<<endl; 
            run_a_instruction(paddress); 
            cout<<"此指令执行是否修改所在页lnumber="<<lnumber<<"(y/n?) "; 
            char change; 
            cin>>change; 
             if(tolower(change)=='y'){
                 page[lnumber].write=1; 
                 print_page_and_fifoqueue(); } 
    
            }
              else{ 
              cout<<lnumber<<"输出该页的页号--表示硬件产生缺页中断"<<endl; 
              do_page_fault(lnumber);
              continue; 
              } 
              cout<<"输入下一条指令的逻辑地址((0~32767),-1 to end)
    "; 
              cin>>laddress; 
             while(laddress>32767){ 
                     cout<<"worse(0~32767)(-1 to end)"<<endl; 
                     cin>>laddress; } 
        } 
        cout<<"进程运行结束!"<<endl; 
        system("PAUSE"); 
         return 0; 
    } 
    void initial(void) 
    
    { 
        int i; 
        for(i=0; i<=5; i++){ 
          page[i].lnumber=i; 
          if(i<=M-1){
              cout<<"输入页号为"<<i<<" 所在内存的物理块号(预装入前四个页面):"; 
              cin>>page[i].pnumber; 
             page[i].flag=1; 
          } 
    
     } 
     head=0; 
     for(i=0; i<=M-1; i++) 
         p[i]=i; 
    
    } 
    voidprint_page_and_fifoqueue(void) 
    
    { 
    
       int i; 
      cout<<"输出页表!
    "; cout<<setw(10)<<"lnumber"<<setw(9)<<"flag"<<setw(10)<<"pnumber"<<setw(10)<<"write"<<setw(10)<<"dnumber"<<endl; 
       for(i=0; i<=N-1; i++) 
       cout<<setw(7)<<page[i].lnumber<<setw(10)<<page[i].flag<<setw(10)<<page[i].pnumber<<setw(10)<<page[i].write<<setw(10)<<page[i].dnumber<<endl; 
    cout<<"输出FIFO对列:
    "; 
    cout<<setw(10)<<"NO"<<setw(40)<<"page(已在主存的页号lnumber)
    "; 
    cout<<"head="<<head<<endl; 
    for(i=0; i<=M-1;i++) 
    cout<<setw(10)<<i<<setw(15)<<p[i]<<endl; 
    
    } 
    intdo_mmap(intladdress) 
    
    { 
    intlnumber, ad, pnumber, paddress; 
    lnumber=laddress>>10; 
    ad=laddress&0x3ff; 
    pnumber=page[lnumber].pnumber; 
    paddress=pnumber<<10|ad; 
    returnpaddress; 
    
    } 
    voidrun_a_instruction(intpaddress) 
    
    { 
    
     cout<<paddress<<" 输出物理地址--表示指令执行完成"<<endl; 
    
    } 
     voidrun_first_instructon(intladdress) 
    
    { 
    
     intlnumber, ad, pnumber, paddress; 
     lnumber=laddress>>10;
     if(page[lnumber].flag==1) 
     paddress=do_mmap(laddress); 
     cout<<paddress<<"输出转换后的物理地址"<<endl; 
     run_a_instruction(paddress); 
     cout<<"此指令执行(0x0000)是否修改所在页面lnumber="<<lnumber<<"(y/n?) "; 
     char change; 
     cin>>change; 
     if(tolower(change)=='y'){ 
        page[lnumber].write=1; 
        print_page_and_fifoqueue(); 
    } 
     cout<<"********第一条指令执行完成(地址为0x0000)***********"<<endl; 
    
    } 
    voiddo_page_fault(intlnumber) 
    
    { 
      int j; 
      j=p[head]; 
      p[head]=lnumber; 
       head=(head+1)%M; 
       if(page[j].write==1) 
      write_to_harddisk(j); 
     page[j].flag=0; 
    page[lnumber].flag=1; 
    page[lnumber].write=0; 
    page[lnumber].pnumber=page[j].pnumber;
    cout<<lnumber<<"输出该页--表示该页调入了主存"<<endl;
    cout<<"按任意键将查看“页面置换”之后的页表page[N]和FIFO队列信息"<<endl; 
    system("PAUSE"); 
    print_page_and_fifoqueue(); 
    }

    四、实验总结

    实验比较难以理解,因为学的知识太多,并不能什么都学精,希望自己可以慢慢地深入了解。

  • 相关阅读:
    echarts 图表缩放 X轴Y轴数据缩放
    avue大屏 avuedata echarts图形数据过多自动滚动
    地图自定义弹窗 高德地图信息窗体 鼠标点击地图点标记显示弹窗html
    地图自定义弹窗 高德地图信息窗体 鼠标点击地图点标记显示弹窗vue
    自动刷新页面的实现方法总结
    vs2008 切换到试图代码后自动关闭问题
    时间差值
    Array.prototype.slice() 方法
    Array.prototype.slice.call()详解及转换数组的方法
    [UNIX网络编程1.0]源代码在linux系统下的实现
  • 原文地址:https://www.cnblogs.com/xy1015/p/4599132.html
Copyright © 2020-2023  润新知