操作系统实验二-虚拟存储器/内存管理(二)

简介: 操作系统实验二-虚拟存储器/内存管理

2.完整代码

FIFO.cpp

#include<stdlib.h>
#include<iostream>
using namespace std;
const int blocklen = 128;
const int M = 4;//主存页面数
const int N = 12;//指令数
int m = 4;
int n = 12;
int k = 0;//FIFO的指针
const int PageSize = 7;//作业需要的页面数
int pageSize = 7;
struct PAGE {
  int flag;//标志
  int blockNum;//主存块号
  int diskPos;//在磁盘上位置
  int editFlag;//修改标志
  PAGE() {
    flag = blockNum = diskPos = editFlag = 0;
  }
};
int P[M];//主存
struct instruct {
  string op;//操作
  int pageNum;//页号
  int unitNum;//单元号
  void print() {
    cout << "Operation:" << op << " Page num:" << pageNum << "  Unit num:" << unitNum << endl;
  }
  instruct(string _op="",int _pageNum=0,int _unitNum=0 ) {
    op = _op;
    pageNum = _pageNum;
    unitNum = _unitNum;
  }
};
instruct inst[105];
PAGE page[105];
void input() {//手动输入
  cout << "input the size of pages in main storage:";
  cin >> m; 
  cout << "input the size of pages of the process:";
  cin >> pageSize;
  cout << "input the number of instructions:";
  cin >> n;
  for (int i = 0; i < m; i++) {
    cout << "input flag,blockNum,diskPos:";
    int flag, blocknum, diskpos;
    cin >> flag>>blocknum>>diskpos;
    page[i].flag = flag;
    if (flag == 1) {
      P[k] = i;
      k = (k + 1) % m;
    }
    page[i].blockNum = blocknum;
    page[i].diskPos = diskpos;
  }
  for (int i = 0; i < n; i++) {
    cout << "input operation,pagenum,unitnum:";
    string op;
    int pagenum, unitnum;
    cin >> op;
    cin >> pagenum >> unitnum;
    inst[i] = { op,pagenum,unitnum };
  }
  k = 0;
  return;
}
void init() {//输入实验指导书上内容
  page[0].flag = 1;
  page[0].blockNum = 5;
  page[0].diskPos = 011;
  page[1].flag = 1;
  page[1].blockNum = 8;
  page[1].diskPos = 012;
  page[2].flag = 1;
  page[2].blockNum = 9;
  page[2].diskPos = 013;
  page[3].flag = 1;
  page[3].blockNum = 1;
  page[3].diskPos = 021;
  page[4].diskPos = 022;
  page[5].diskPos = 023;
  page[6].diskPos = 121;
  inst[0] = { "+",0,70 };
  inst[1] = { "+",1,50 };
  inst[2] = { "*",2,15 };
  inst[3] = { "save",3,21 };
  inst[4] = { "get",0,56 };
  inst[5] = { "-",6,40 };
  inst[6] = { "move",4,53 };
  inst[7] = { "+",5,23 };
  inst[8] = { "save",1,37 };
  inst[9] = { "get",2,78 };
  inst[10] = { "+",4,1 };
  inst[11] = { "save",6,84 };
  P[0] = 0;
  P[1] = 1;
  P[2] = 2;
  P[3] = 3;
}
void interrupt(int L) {//中断处理
  int j = P[k];//要调出的页面
  if (page[j].editFlag == 1)
    cout << "out J!" << j << endl;//调出当前页
  page[j].flag = 0;
  cout << "in L" << L << endl;//调入页面
  P[k] = L;
  k = (k + 1) % m;
  page[L].flag = 1;//将页装入主存
}
void cpuwork() {
  for (int i = 0; i < n; i++) {
    int L = inst[i].pageNum;//取指令中访问的页号
    inst[i].print();
    if (page[L].flag == 1) {//查页表
      int addr = page[L].blockNum * blocklen + inst[i].unitNum;//输出绝对地址
      if (inst[i].op == "save")//是否为存指令
        page[L].editFlag = 1;
      cout << "absolute address:" << addr << endl;
    }
    else {
      cout << "******interrupt!*****\n";
      interrupt(L);
      i--;//重新查页表
    }
    cout << "********************************\npages in main storage\n";
    for (int i = 0; i <m; i++)
      cout << "Page num:" << P[i] << " Block num:" << page[P[i]].blockNum << " Edit Flag:" << page[P[i]].editFlag
      <<" Disk pos:" << page[P[i]].diskPos <<endl;
    cout << "********************************\n\n"
cout << "********************************\npages of the work\n";
    for (int i = 0; i <pageSize; i++)
      cout << "Page num:" << i <<" flag:" <<page[i].flag<<" Block num:" << page[i].blockNum << " Edit Flag:" << page[i].editFlag
      <<" Disk pos:" << page[i].diskPos <<endl;
    cout << "********************************\n\n";
  }
}
int main() {
  int choose;
  cout << "Choose input:1. auto 2.by hand";
  cin >> choose;
  if (choose == 1)
    init();
  else
    input();
  cpuwork();
}

LRU.cpp

#include<stdlib.h>
#include<iostream>
using namespace std;
const int blocklen = 128;
const int M = 4;//主存页面数
const int N = 12;//指令数
int m = 4;
int n = 12;
int k = 0;//FIFO的指针
const int PageSize = 7;//作业需要的页面数
int pageSize = 7;
struct PAGE {
  int flag;//标志
  int blockNum;//主存块号
  int diskPos;//在磁盘上位置
  int editFlag;//修改标志
  PAGE() {
    flag = blockNum = diskPos = editFlag = 0;
  }
};
int P[50];//主存
struct instruct {
  string op;//操作
  int pageNum;//页号
  int unitNum;//单元号
  void print() {
    cout << "Operation:" << op << " Page num:" << pageNum << "  Unit num:" << unitNum << endl;
  }
  instruct(string _op = "", int _pageNum = 0, int _unitNum = 0) {
    op = _op;
    pageNum = _pageNum;
    unitNum = _unitNum;
  }
};
instruct inst[105];
PAGE page[105];
void input() {
  cout << "input the size of pages in main storage:";
  cin >> m;
  cout << "input the size of pages of the process:";
  cin >> pageSize;
  cout << "input the number of instructions:";
  cin >> n;
  for (int i = 0; i < m; i++) {
    cout << "input flag,blockNum,diskPos:";
    int flag, blocknum, diskpos;
    cin >> flag >> blocknum >> diskpos;
    page[i].flag = flag;
    if (flag == 1) {
      P[k] = i;
      k = (k + 1) % m;
    }
    page[i].blockNum = blocknum;
    page[i].diskPos = diskpos;
  }
  for (int i = 0; i < n; i++) {
    cout << "input operation,pagenum,unitnum:";
    string op;
    int pagenum, unitnum;
    cin >> op;
    cin >> pagenum >> unitnum;
    inst[i] = { op,pagenum,unitnum };
  }
  k = 0;
  return;
}
void init() {//实验指导书上的页表
  page[0].flag = 1;
  page[0].blockNum = 5;
  page[0].diskPos = 011;
  page[1].flag = 1;
  page[1].blockNum = 8;
  page[1].diskPos = 012;
  page[2].flag = 1;
  page[2].blockNum = 9;
  page[2].diskPos = 013;
  page[3].flag = 1;
  page[3].blockNum = 1;
  page[3].diskPos = 021;
  page[4].diskPos = 022;
  page[5].diskPos = 023;
  page[6].diskPos = 121;
  inst[0] = { "+",0,70 };
  inst[1] = { "+",1,50 };
  inst[2] = { "*",2,15 };
  inst[3] = { "save",3,21 };
  inst[4] = { "get",0,56 };
  inst[5] = { "-",6,40 };
  inst[6] = { "move",4,53 };
  inst[7] = { "+",5,23 };
  inst[8] = { "save",1,37 };
  inst[9] = { "get",2,78 };
  inst[10] = { "+",4,1 };
  inst[11] = { "save",6,84 };
  P[0] = 0;
  P[1] = 1;
  P[2] = 2;
  P[3] = 3;
}
void interrupt(int L) {//中断服务
  int j = P[m - 1];//栈底页面调出
  if (page[j].editFlag == 1)
    cout << "out J!" << j << endl;//调出该页面
  page[j].flag = 0;
  cout << "in L" << L << endl;
  P[3] = P[2];
  P[2] = P[1];
  P[1] = P[0];
  P[0] = L;//调整主存中的页面
  page[L].flag = 1;
}
void cpuwork() {
  for (int i = 0; i < n; i++) {
    int L = inst[i].pageNum;//取指令访问的页号
    inst[i].print();
    if (page[L].flag == 1) {
      int addr = page[L].blockNum * blocklen + inst[i].unitNum;//形成绝对地址
      if (inst[i].op == "save")
        page[L].editFlag = 1;
      cout << "absolute address:" << addr << endl;
      int pos = 0;//调整主存中的页面
      for (int i = 1; i <m; i++) {
        if (P[i] == L) {
          pos = i;
          break;
        }
      }
      if(pos!=0)
        for (int i = pos; i >= 1; i--)
          P[i] = P[i - 1];
      P[0] = L;
    }
    else {
      cout << "******interrupt!*****\n";
      interrupt(L);
      i--;
    }
    cout << "********************************\npages in main storage\n";
    for (int i = 0; i < m; i++)
      cout << "Page num:" << P[i] << " Block num:" << page[P[i]].blockNum << " Edit Flag:" << page[P[i]].editFlag
      << " Disk pos:" << page[P[i]].diskPos << endl;
    cout << "********************************\n\n";
cout << "********************************\npages of the work\n";
    for (int i = 0; i <pageSize; i++)
      cout << "Page num:" << i <<" flag:" <<page[i].flag<<" Block num:" << page[i].blockNum << " Edit Flag:" << page[i].editFlag
      <<" Disk pos:" << page[i].diskPos <<endl;
    cout << "********************************\n\n";
  }
}
int main() {
  int choose;
  cout << "Choose input:1. auto 2.by hand";
  cin >> choose;
  if (choose == 1)
    init();
  else
    input();
  cpuwork();

(4)程序运行结果

 打印初始页表,每次调出(要调出一页时)和装入的页号,执行最后一条指令后在主存中的页面号(即数组的值)。

FIFO算法

 图为初始页表,与实验指导书是完全一致的。

 执行到第5条指令,调出第0页时,装入了第6页。因为修改标志位为0,所以不必将“0”调出并输出。

 执行到第6条指令,调出第1页时,装入了第4页。因为修改标志位为0,所以同样不必将“1”调出并输出。

 执行到第7条指令,调出第2页时,装入了第5页。因为修改标志位为0,所以同样不必将“2”调出并输出。

 执行到第8条指令,调出第3页时,装入了第1页。因为修改标志位为1,所以需要将“3”输出。

 执行到第9条指令,调出第6页时,装入了第2页。因为修改标志位为0,所以同样不必将“6”调出并输出。

 执行到最后一条指令,调出第4页时,装入了第6页。因为修改标志位为0,所以同样不必将“4”调出并输出。同时,图10也是执行完最后一条指令时主存中的页面号。

LRU算法

 图为初始页表,无论采用哪种算法,其与实验指导书是完全一致的。

 图为第一次中断时,将数组底部的1调出,将6调入。并修改栈内情况。

 图为第二次中断时,将数组底部的2调出,将4调入。并修改栈内情况。

 图为第三次中断时,将数组底部的3调出,将5调入。并修改栈内情况。由于3的修改标志位为1,所以需要将3输出。

 图为第四次中断时,将数组底部的0调出,将1调入。并修改栈内情况。

 图为第五次中断时,将数组底部的6调出,将2调入。并修改栈内情况。

 图为第六次中断时,将数组底部的5调出,将6调入。并修改栈内情况。

 全部指令运行完成后,留在主存中的页面号。

五、思考题

 如果你有兴趣的话,可把两种页面调度算法都做一下,比较两种调度算法的效率(哪种调度算法产生缺页中断的次数少);分析在什么情况下采用哪种调度算法更有利?

 如上文,已实现并运行两种页面调度算法。其中,FIFO算法产生了6次缺页中断,缺页中断率为6/12=50%。LRU算法产生了6次缺页中断,缺页中断率为6/12=50%。对于实验指导书给的数据,两种算法效率相同。缺页中断次数相同在大多数情况下尤其是执行循环语句时,LRU算法更有利。

六、实验感悟

目录
相关文章
|
1月前
|
算法
数据结构实验之操作系统打印机管理器问题
本实验旨在通过实现操作系统中的打印机管理器问题,掌握队列的基本操作如入队、出队等,利用队列的先进先出特性解决先申请先打印的问题。实验包括队列的初始化、入队、出队、打印队列内容等功能,并通过菜单式界面进行交互。实验结果显示基本功能可正常执行,但在连续操作时存在执行失败的情况,需进一步优化。
42 4
|
3月前
|
存储 Linux 调度
深入理解操作系统:从进程管理到内存分配
【8月更文挑战第44天】本文将带你深入操作系统的核心,探索其背后的原理和机制。我们将从进程管理开始,理解如何创建、调度和管理进程。然后,我们将探讨内存分配,了解操作系统如何管理计算机的内存资源。最后,我们将通过一些代码示例,展示这些概念是如何在实际操作系统中实现的。无论你是初学者还是有经验的开发者,这篇文章都将为你提供新的视角和深入的理解。
|
19天前
|
C语言 开发者 内存技术
探索操作系统核心:从进程管理到内存分配
本文将深入探讨操作系统的两大核心功能——进程管理和内存分配。通过直观的代码示例,我们将了解如何在操作系统中实现这些基本功能,以及它们如何影响系统性能和稳定性。文章旨在为读者提供一个清晰的操作系统内部工作机制视角,同时强调理解和掌握这些概念对于任何软件开发人员的重要性。
|
18天前
|
Linux 调度 C语言
深入理解操作系统:从进程管理到内存优化
本文旨在为读者提供一次深入浅出的操作系统之旅,从进程管理的基本概念出发,逐步探索到内存管理的高级技巧。我们将通过实际代码示例,揭示操作系统如何高效地调度和优化资源,确保系统稳定运行。无论你是初学者还是有一定基础的开发者,这篇文章都将为你打开一扇了解操作系统深层工作原理的大门。
|
28天前
|
算法 调度 开发者
深入理解操作系统:从进程管理到内存分配
本文旨在为读者提供一个深入浅出的操作系统知识之旅,从进程管理的基础概念出发,探索内存分配的策略与技巧。我们将通过实际代码示例,揭示操作系统背后的逻辑与奥秘,帮助读者构建起对操作系统工作原理的直观理解。文章不仅涵盖理论知识,还提供实践操作的指导,使读者能够将抽象的概念转化为具体的技能。无论你是初学者还是有一定基础的开发者,都能在这篇文章中找到有价值的信息和启发。
|
1月前
|
算法 调度 C++
深入理解操作系统:从进程管理到内存分配
【10月更文挑战第42天】本文将带你进入操作系统的神秘世界,探索其核心概念和关键技术。我们将从进程管理开始,了解操作系统如何协调和管理多个程序的运行;然后,我们将深入研究内存分配,看看操作系统如何有效地分配和管理计算机的内存资源。通过这篇文章,你将获得对操作系统工作原理的深入理解,并学会如何编写高效的代码来利用这些原理。
|
2月前
|
分布式计算 算法 大数据
探索操作系统的核心:调度与内存管理机制
【10月更文挑战第11天】 本文深入探讨了操作系统中两大核心功能——调度与内存管理机制。通过分析调度算法、进程状态转换及内存分配策略等关键方面,揭示了它们如何共同维护系统性能和稳定性。旨在为读者提供对操作系统内部运作的深刻理解,同时引起对优化策略的思考。
77 5
|
2月前
|
算法
深入理解操作系统:内存管理机制的探索之旅
【10月更文挑战第2天】在数字世界的浩瀚海洋中,操作系统犹如一艘精密的航船,承载着软件与硬件的和谐共舞。本文将揭开内存管理的神秘面纱,从基础概念到高级策略,引领读者领略操作系统内存分配的智慧。通过深入浅出的解释和生动的比喻,我们一同遨游在内存的江河之中,感受操作系统如何巧妙地协调资源,确保数据的有序流动。让我们跟随内存的脚步,探索那些隐藏在每次点击、每次命令背后的奥秘。
|
2月前
|
监控 开发者
深入理解操作系统:内存管理的艺术
【10月更文挑战第2天】在数字世界的幕后,操作系统扮演着至关重要的角色。本文将深入探索操作系统的心脏——内存管理,揭示它是如何协调和管理计算机的宝贵资源。通过浅显易懂的语言和生活化的比喻,我们将一起走进内存管理的奥秘世界,了解它的原理、机制以及为何对整个系统的性能和稳定性有着不可替代的影响。无论你是技术新手还是资深开发者,这篇文章都将为你打开新的视角,让你对日常使用的设备有更深层次的认识和尊重。
|
2月前
|
缓存 算法 调度
深入浅出操作系统:从进程管理到内存优化
本文旨在为读者提供一次深入浅出的操作系统之旅。我们将从进程管理的基本概念出发,逐步深入到内存管理的复杂世界,最终探索如何通过实践技巧来优化系统性能。文章将结合理论与实践,通过代码示例,帮助读者更好地理解操作系统的核心机制及其在日常技术工作中的重要性。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往操作系统深层次理解的大门。