操作系统——用C++模拟一个分段存储管理
一、需求分析段式存储管理是基于为用户提供一个方便灵活的程序设计环境而提出来的。段式管理的基本思想是:把程序按内容或过程(函数)关系分成段,每段有自己的名字。一个用户作业或进程所包含的段对应于一个二维线性虚拟空间,也就是一个二维虚拟存储器。段式管理程序以段为单位分配内存,然后通过地址映射机构把段式虚拟地址转换成实际的内存物理地址。和页式管理时一样,段式管理也采用只把那些经常访问的段驻留...
一、需求分析
段式存储管理是基于为用户提供一个方便灵活的程序设计环境而提出来的。段式管理的基本思想是:把程序按内容或过程(函数)关系分成段,每段有自己的名字。一个用户作业或进程所包含的段对应于一个二维线性虚拟空间,也就是一个二维虚拟存储器。段式管理程序以段为单位分配内存,然后通过地址映射机构把段式虚拟地址转换成实际的内存物理地址。和页式管理时一样,段式管理也采用只把那些经常访问的段驻留内存,而把那些在将来一段时间内不被访问的段放入外存,待需要时自动调入的方法现实二维虚拟存储器。
模拟设计段式存储管理的分配与回收要求能够输入给定的内存大小,进程的个数,每个进程的段数及段大小;当某进程提出申请空间的大小后,显示能否满足申请,以及为该进程分配资源后有关内存空间使用的情况;显示回收后内存空间的使用情况。
二、系统设计
(一)系统中的数据定义
结构体struct duan 用来表示段
其中:
long capacity 表示该段的长度
long addr 表示起始逻辑地址
long realaddr 表示该段实际起始地址
结构体 struct duanbiao 用来表示段表
其中:
char processname[20] 表示进程的名字
Int Isdiaoyong 表示是否被调用
Int num 表示段的数目
Long total 表示该进程的总占用量
Long neicun=0 表示内存初始化
Int duanbiaonum=0 表示段表数目初始化为0
Long zhanyongneicun 表示占用的内存
Long baseaddr=0 表示所有段的基址初始化为0
Void show1()
Void show() 两个显示函数用来显示当前内存占用情况以及段表
Void apply() 表示申请进程和内存的函数
Void diaodu() 表示对进程进行调度的函数(分配内存)
Void reclaim() 表示对内存进行回收的函数
Void zhuanhuan() 地址转换的函数
(二)系统的功能设计
2.2.1 段式虚存空间
段式管理管理把一个进程的虚拟地址空间设计成二维结构,即短号s与段内相对地址w。与页式管理时不一样的是,页式管理中,被划分的页号按顺序编号递增排列,属一维空间,而段式管理中的段号与段号之间无顺序关系。另外,段的划分也不像页的划分那样具有相同的页长,段的长度的不固定的。每个段定义一组逻辑上完整的程序或数据。
每个段是一个首地址为零、连续的一维线性空间。根据需要,段长课动态增长。对段式虚地址空间的访问包括两个部分:段名和段内地址。其中的段名经编译程序和链接程序编译链接后转换成机器内部可以识别的段号和段内单元号
2.2.2 段式存储管理的内存分配和回收
段式管理中以段为单位分配内存,每段分配一个连续的内存区。由于各段长度不等,所以这些存储区的大小不一。而且,同一进程所包含的各段之间不要求连续。
段式管理的内存分配与释放在作业或进程的执行过程中动态进行。
动态分配过程:
首先,段式管理为进程或作业分配部分内存,以作为该进程的工作区和放置即将执行的程序段。
随着进程的执行,进程根据需要随时申请调入新段和释放老段。
进程对内存区的申请和释放可分为两种情况:
一种是当进程要求调入某一段时,内存中有足够的空闲区满足该段的内存要求
另一种是内存中没有足够的空闲区满足该段的内存要求。
除了初始分配之外,段的动态分配是在CPU所要访问的指令和数据不在内存时产生缺段中断的情况下发生的。
因此,段的淘汰或置换算法实际上是缺段中断处理过程的一部分。
2.2.3 段式存储管理的地址转换
(1)段表(segment mapping table)
和页式管理方案类似,段式管理程序在进行初始内存分配之前,首先根据用户要求的内存大小为一个作业或进程建立一个段表。
与页式管理时一样,段式管理也是通过段表来进行内存管理。
(2)动态地址变换
一般在内存中给出一块固定的区域放置段表。
当某进程开始执行时,管理程序首先把该进程的段表始址放入段表地址寄存器。
通过访问段表寄存器,管理程序得到该进程的段表始址从而可开始访问段表。
然后,由虚地址中的段号s为索引,查段表。
若该段在内存,则判断其存取控制方式是否有错。
如果存取控制方式正确,则从段表相应表目中查出该段在内存的起始地址,并将其和段内相对地址w相加,从而得到实际内存地址。
如果该段不在内存,则产生缺段中断将CPU控制权交给内存分配程序。
内存分配程序首先检查空闲区链,以找到足够长度的空闲区来装入所需要的段。
如果内存中的可用空闲区总数小于所要求的段长时,则检查段表中访问位,以淘汰那些访问概率低的段并将需要段调入。
(三)系统的详细设计
2.3 存储结构说明
在此段页式存储管理系统中,我们采用以下数据结构来存储数据,存储结构用结构体和结构体数组来实现:
2.3.1段
段长
起始逻辑地址
实际起始地址
struct duan
{
long capacity;//该段的长度
long addr;//起始逻辑地址
long realaddr;//该段实际起始地址
};
2.3.2段表
段
进程名
调用情况
段数
该进程的总占用量
struct duanbiao
{
duan duans[10];
char processname[20]; // 进程的名字
int Isdiaoyong; //是否被调用
int num; //段的数目
long total; //该进程的总占用量
};
2.2.3程序流程图
三、系统实现及运行结果
(一)系统开发工具
Windows 10 、
Code :: Blocks、
Microsoft Vsio 、
(二)系统运行界面及结果
图3.1
图3.2
图3.3
图3.4
图3.5
图3.6
图3.7
图3.8
图3.9
四、总结
本次系统中,主要是利用简单的数据结构和VC的简单的控制台程序,采用自己定义数据模拟段页式存储管理的方式,简单明快的是给用户一个功能菜单,然后只要不退出就可以进行各种地址转化测试而数据结构部分,采用结构体数组比较容易掌握的格式,是的查询过程简单化。总的来说,利用简单的思想较为完整的模拟了段式存储的各个步骤。
五、源代码
#include <iostream> #include<stdlib.h> #include <string.h> #include<stdio.h> #include <iomanip> using namespace std; struct duan { long capacity;//该段的长度 long addr;//起始逻辑地址 long realaddr;//该段实际起始地址 }; struct duanbiao { duan duans[10]; char processname[20]; // 进程的名字 int Isdiaoyong; //是否被调用 int num; //段的数目 long total; //该进程的总占用量 }; long neicun=0; int duanbiaonum=0; //段表的数目 long zhanyongneicun=0; // 占用的内存 long baseaddr=0; duanbiao duanbiaos[10]; void show1(int ); void show(); void diaodu() { cout<<"您要调度的进程是:p"; int n; cin>>n; if(n>duanbiaonum) cout<<"段表不存在!"<<endl; else if(duanbiaos[n-1].Isdiaoyong==1) cout<<"操作错误,该进程已经被调入到内存!"<<endl; else if(duanbiaos[n-1].total>neicun-zhanyongneicun) cout<<"内存空间不足,调度不成功!"<<endl; else { cout<<"下面对进程"<<duanbiaos[n-1].processname<<"进行地址转化:"<<endl; for(int j=0;j<duanbiaos[n-1].num;j++) { cout<<"正在进行第"<<j+1<<"段的地址转换,请稍后......"<<endl; duanbiaos[n-1].duans[j].realaddr=duanbiaos[n-1].duans[j].addr+zhanyongneicun; cout<<"第"<<j+1<<"段的地址转换成功!"<<endl; } zhanyongneicun=zhanyongneicun+duanbiaos[n-1].total; duanbiaos[n-1].Isdiaoyong =1; cout<<"调度后的结果是:"<<endl; show1(n-1); } } void reclaim() { cout<<"您要回收内存的进程是:"; int n; cin >> n; for(int j=0;j<duanbiaos[n-1].num;j++) { duanbiaos[n-1].duans[j].addr=0; duanbiaos[n-1].duans[j].realaddr=0;//duanbiaos[n-1].duans[j].addr-zhanyongneicun duanbiaos[n-1].duans[j].capacity=0; } zhanyongneicun=0;//zhanyongneicun-duanbiaos[n-1].total; duanbiaos[n-1].Isdiaoyong =0; cout << "回收之后的结果是:" << endl; show1(n-1); } void zhuanhuan() { int n,i,j; cout<<"请输入进程:p"; cin>>n; if(n>duanbiaonum) cout<<"进程不存在或没被调度!"<<endl; else if(duanbiaos[n-1].Isdiaoyong==1) { cout<<"请输入段号:"<<endl; cin>>i; cout<<"输入偏移地址:"<<endl; cin>>j; if(i>duanbiaos[n-1].num) { cout<<"段号超出范围"<<endl; } else if(j>duanbiaos[n-1].duans[i-1].capacity) { cout<<"段内偏移地址超出范围"<<endl; } else { cout<<"转换后的地址为"<<endl; cout<<duanbiaos[n-1].duans[i-1].realaddr+j<<endl; } } else cout<<"该进程没有调入内存"<<endl; } void apply() { printf("请输入进程的名字:"); cin>>duanbiaos[duanbiaonum].processname; printf("请输入该进程的段数:"); cin>>duanbiaos[duanbiaonum].num; int paddr=0; for(int j=0;j<duanbiaos[duanbiaonum].num;j++) { cout<<"进程第"<<j+1<<"段的大小是:"; cin>>duanbiaos[duanbiaonum].duans[j].capacity ; duanbiaos[duanbiaonum].duans[j].addr=paddr; paddr=paddr+duanbiaos[duanbiaonum].duans[j].capacity; } duanbiaos[duanbiaonum].Isdiaoyong=0; duanbiaos[duanbiaonum].total=paddr; duanbiaonum++; } void show1(int i) { cout<<"进程p"<<i+1<<":"<<endl; cout<<"名字:"<<duanbiaos[i].processname<<endl; cout<<"该进程所占用的存储空间:"<<duanbiaos[i].total<<endl; if(duanbiaos[i].Isdiaoyong==0) cout<<"进程状态:未调用"<<endl; else cout<<"进程状态:已调用"<<endl; cout<<"____________________________________________"<<endl; cout<<"段 号 始址 内存始址 大小"<<endl; for(int j=0;j<duanbiaos[i].num;j++) { cout<<" "<<j+1<<setw(11)<<duanbiaos[i].duans[j].addr; if(duanbiaos[i].Isdiaoyong==0) cout<<" "; else cout<<setw(11)<<duanbiaos[i].duans[j].realaddr; cout<<setw(8)<<duanbiaos[i].duans[j].capacity<<endl ; } cout<<"____________________________________________"<<endl; } void show() { for(int i=0;i<duanbiaonum;i++) show1(i); } int main(int argc, char* argv[]) { char c; cout<<"请输入内存的大小:"; cin>>neicun; cout<<"*******************************************************************************"<<endl; cout<<" 1:申请进程(a) "<<endl; cout<<" 2:显示进程(s) "<<endl; cout<<" 3:调度进程(d) "<<endl; cout<<" 4.地址转换(z) "<<endl; cout<<" 5:回收内存(r)"<<endl; cout<<" 6:退 出(e)"<<endl; cout<<"********************************************************************************"<<endl; while(1) { cout<<"请选择服务种类(a/s/d/z/r/e):"; cin>>c; if(c=='e') { cout<<"程序运行完毕,执行退出程序!"<<endl; break; } else if(c=='a') apply(); else if(c=='s') show(); else if(c=='d') diaodu(); else if(c=='z') zhuanhuan(); else if(c=='r') reclaim(); else cout<<"error!请重新输入!"<<endl; } return 0; }
更多推荐
所有评论(0)