一、实验目的
1.理解操作系统进程管理中进行进程调度的过程和编程方法,创建进程控制块PCB。
2.理解进程的状态及变化,动态显示每个进程的当前状态及进程的调度情况。掌握几种调度算法。
理解几种进程调度的方式
用代码将几种进程调度的方式表现出来
二、实验原理
(1)先到先服务:按照进程提交给系统的先后次序来进行调度。
(2)短作业优先:按照进程所要求的运行时间来衡量。
(3)时间片轮转:根据先来先服务排序,以一个时间片为单位,依次执行不同的进程。
(4)响应比高者优先(HRRN)调度算法,为每个作业设置一个优先权(响应比),调度之前先计算各作业的优先权,优先数高者优先调度。
RP(响应比)=作业周转时间/作业运行时间=1+作业等待时间/作业运行时间
三、实验代码
数据结构:
typedef struct node
{
int number; // 作业号
int reach_time;// 作业抵达时间
int need_time;// 作业的执行时间
int privilege;// 作业优先权
float excellent;// 响应比
int start_time;// 作业开始时间
int wait_time;// 等待时间
int visited;// 作业是否被访问过
bool isreached;// 作业是否已经抵达
}job;
函数说明:
void initial_jobs()
//初始化所有作业信息
void reset_jinfo()
//重置所有作业信息
int findminjob(job jobs[],int count)
//找到执行时间最短的作业。输入参数:所有的作业信息及待查找的作业总数,输出为执行时间最短的作业id
int findrearlyjob(job jobs[],int count)
//找到达到最早的作业 输入参数:所有的作业信息及待查找的作业总数,输出参数为最早达到的作业id
void readJobdata()
//读取作业的基本信息
void FCFS()
//先来先服务算法
void SFJschdulejob(job jobs[],int count)
//短作业优先算法 输入参数:所有的作业信息及待查找的作业总数
#include
#include
#include
typedef enum __bool { false = 0, true = 1, } bool;
//最大作业数量
#define MAXJOB 50
//作业的数据结构
typedef struct node
{
int number;//作业号
int reach_time;//作业抵达时间
int need_time;//作业的执行时间
int privilege;//作业优先权
float excellent;//响应比
int start_time;//作业开始时间
int wait_time;//等待时间
int visited;//作业是否被访问过
bool isreached;//作业是否抵达
}job;
job jobs[MAXJOB];//作业序列
int quantity;//作业数量
//初始化作业序列
void initial_jobs()
{
int i;
for(i=0;i
jobs[i].number=0;
jobs[i].reach_time=0;
jobs[i].privilege=0;
jobs[i].excellent=0;
jobs[i].start_time=0;
jobs[i].wait_time=0;
jobs[i].visited=0;
jobs[i].isreached=false;
}
quantity=0;
}
//重置全部作业信息
void reset_jinfo()
{
int i;
for(i=0;i
jobs[i].start_time=0;
jobs[i].wait_time=0;
jobs[i].visited=0;
}
}
//查找当前current_time已到达未执行的最短作业,若无返回-1
int findminjob(job jobs[],int current_time)
{
int mincost = 1000;
int minloc = -1;
int i;
for(i=0;i
if(jobs[i].reach_time<=current_time&&jobs[i].visited == 0){
if(jobs[i].need_time
minloc = i;
}
}
}
if(minloc==-1){
int early_time=10000;
for( i = 0;i
mincost = jobs[i].need_time;
minloc = i;
}else if(jobs[i].reach_timeearly_time&&jobs[i].need_time
minloc = i;
}
}
}
return minloc;
}
//查找最早到达作业,若全部到达返回-1.
int findrearlyjob(job jobs[],int count)
{
int rearlyloc=-1;
int rearlyjob=-1;
int i;
for(i=0;i
if(rearlyloc
if(jobs[i].visited0){
rearlyloc=i;
rearlyjob=jobs[i].reach_time;
}
}
else if(rearlyjob>jobs[i].reach_time&&jobs[i].visited0)
{
rearlyjob=jobs[i].reach_time;
rearlyloc=i;
}
}
return rearlyloc;
}
//读取作业数据
void readJobdata()
{
FILE *fp;
char fname[20];
int i;
//输入测试文件文件名
printf(“please input job data file name\n”);
scanf("%s",fname);
if((fp=fopen(fname,“r”))==NULL)
{
printf(“error, open file failed, please check filename:\n”);
}
else
{
//依次读取作业信息
while(!feof(fp))
{
int num;
if(fscanf(fp,"%d %d %d %d",&jobs[quantity].number,&jobs[quantity].reach_time,&jobs[quantity].need_time,&jobs[quantity].privilege)){
quantity++;
}
}
quantity--;
//打印作业信息
printf("output the origin job data\n");
printf("---------------------------------------------------------------------\n");
printf("\tjobID\treachtime\tneedtime\tprivilege\n");
for(i=0;i
}
//FCFS
void FCFS()
{
int i;
int current_time=0;
int loc;
int total_waitime=0;
int total_roundtime=0;
//获取最近到达的作业
loc=findrearlyjob(jobs,quantity);
//输出作业流
printf("\n\nFCFS算法作业流\n");
printf("------------------------------------------------------------------------\n");
printf("\tjobID\treachtime\tstarttime\twaittime\troundtime\n");
current_time=jobs[loc].reach_time;
//每次循环找出最先到达的作业并打印相关信息
for(i=0;i
if(jobs[loc].reach_time>current_time)
{
jobs[loc].start_time=jobs[loc].reach_time;
current_time=jobs[loc].reach_time;
}
else
{
jobs[loc].start_time=current_time;
}
jobs[loc].wait_time=current_time-jobs[loc].reach_time;
printf("\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\n",jobs[loc].number,jobs[loc].reach_time,jobs[loc].start_time,jobs[loc].wait_time,
jobs[loc].wait_time+jobs[loc].need_time);
jobs[loc].visited=1;
current_time+=jobs[loc].need_time;
total_waitime+=jobs[loc].wait_time;
total_roundtime=total_roundtime+jobs[loc].wait_time+jobs[loc].need_time;
//获取剩余作业中最近到达作业
loc=findrearlyjob(jobs,quantity);
}
printf(“总等待时间:%-8d 总周转时间:%-8d\n”,total_waitime,total_roundtime);
printf(“平均等待时间: %4.2f 平均周转时间: %4.2f\n”,(float)total_waitime/(quantity),(float)total_roundtime/(quantity));
}
//短作业优先作业调度
void SFJschdulejob(job jobs[],int count) //6175432
{
int i;
int current_time = 0;
int total_waitime=0;
int total_roundtime=0;
int loc;
int earlyest = findrearlyjob(jobs,quantity);
loc = findminjob(jobs,jobs[earlyest].reach_time);
//输出作业流
printf("\n\nSFJ算法作业流\n");
printf("------------------------------------------------------------------------\n");
printf("\tjobID\treachtime\tstarttime\twaittime\troundtime\n");
//每次循环找出最短作业作业并打印相关信息e
for(i = 0;i
jobs[loc].start_time = jobs[loc].reach_time;
current_time = jobs[loc].reach_time+jobs[loc].need_time;
jobs[loc].wait_time = 0;
}else{
jobs[loc].start_time = current_time;
jobs[loc].wait_time = current_time-jobs[loc].reach_time;
current_time+=jobs[loc].need_time;
}
printf("\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\n",jobs[loc].number,jobs[loc].reach_time,jobs[loc].start_time,jobs[loc].wait_time,
jobs[loc].wait_time+jobs[loc].need_time);
total_waitime+=jobs[loc].wait_time;
total_roundtime+=jobs[loc].wait_time+jobs[loc].need_time;
jobs[loc].visited=1;
loc = findminjob(jobs,current_time);
}
printf("总等待时间:%-8d 总周转时间:%-8d\n",total_waitime,total_roundtime);
printf("平均等待时间: %4.2f 平均周转时间: %4.2f\n",(float)total_waitime/(quantity),(float)total_roundtime/(quantity));
}
int updatePrivilege(job jobs[],int current_time){
int next = -1;
int max_privilege = -1;
int i;
while(max_privilege==-1){
for(i = 0;imax_privilege){
max_privilege = jobs[i].excellent;
next = i;
}
}
}
if(max_privilege==-1){
int early_time=10000,i;
for(i = 0;icurrent_time&&jobs[i].visited!=1){
early_time = jobs[i].reach_time;
next = i;
jobs[i].excellent = (double)jobs[i].wait_time/(double)jobs[i].need_time;
max_privilege = jobs[i].excellent;
}
}
}
}
return next;
}
//高响应比调度算法
void HRRFschdulejob()
{
int i,j;
for(i = 0;i
job temp = jobs[j];
jobs[j] = jobs[j+1];
jobs[j+1] = temp;
}
}
}
int current_time = 0;
int total_waitime=0;
int total_roundtime=0;
int loc = updatePrivilege(jobs,jobs[0].reach_time);
printf("------------------------------------------------------------------------\n");
printf("\tjobID\treachtime\tstarttime\twaittime\troundtime\n");
for(i = 0;i
jobs[loc].start_time = jobs[loc].reach_time;
jobs[loc].wait_time = 0;
current_time = jobs[loc].start_time+jobs[loc].need_time;
}else{
jobs[loc].start_time = current_time;
jobs[loc].wait_time = current_time - jobs[loc].reach_time;
current_time+=jobs[loc].need_time;
}
printf("\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\n",jobs[loc].number,jobs[loc].reach_time,jobs[loc].start_time,jobs[loc].wait_time,
jobs[loc].wait_time+jobs[loc].need_time);
total_waitime+=jobs[loc].wait_time;
total_roundtime+=jobs[loc].wait_time+jobs[loc].need_time;
jobs[loc].visited = 1;
if(i!=quantity-1){
loc = updatePrivilege(jobs,current_time);
}
}
printf(“总等待时间:%-8d 总周转时间:%-8d\n”,total_waitime,total_roundtime);
printf(“平均等待时间: %4.2f 平均周转时间: %4.2f\n”,(float)total_waitime/(quantity),(float)total_roundtime/(quantity));
}
//优先权高者优先调度算法
void HPF(job jobs[])
{
int i,j;
for(i = 0;i
job temp = jobs[j];
jobs[j] = jobs[j+1];
jobs[j+1] = temp;
}
}
}
for(i = 0;i
job temp = jobs[j];
jobs[j] = jobs[j+1];
jobs[j+1] = temp;
}
}
}
int current_time = 0;
int total_waitime=0;
int total_roundtime=0;
int loc = 0;
printf("------------------------------------------------------------------------\n");
printf("\tjobID\treachtime\tstarttime\twaittime\troundtime\n");
for(i = 0;i
jobs[loc].start_time = jobs[loc].reach_time;
current_time = jobs[loc].start_time+jobs[loc].need_time;
}else{
jobs[loc].start_time = current_time;
current_time+=jobs[loc].need_time;
}
jobs[loc].wait_time = jobs[loc].start_time-jobs[loc].reach_time;
printf("\t%-8d\t%-8d\t%-8d\t%-8d\t%-8d\n",jobs[loc].number,jobs[loc].reach_time,jobs[loc].start_time,jobs[loc].wait_time,
jobs[loc].wait_time+jobs[loc].need_time);
total_waitime+=jobs[loc].wait_time;
total_roundtime+=jobs[loc].wait_time+jobs[loc].need_time;
jobs[loc].visited = 1;
int next = -1;
int max_privilege = -1;
for(j = 0;j
if(jobs[j].visited!=1&&jobs[j].privilege>max_privilege){
max_privilege = jobs[j].privilege;
next = j;
}
}
if(next
next = loc+1;
}
loc = next;
}
printf(“总等待时间:%-8d 总周转时间:%-8d\n”,total_waitime,total_roundtime);
printf(“平均等待时间: %4.2f 平均周转时间: %4.2f\n”,(float)total_waitime/(quantity),(float)total_roundtime/(quantity));
}
int main()
{
initial_jobs();
readJobdata();
FCFS();
initial_jobs();
readJobdata();
SFJschdulejob(jobs,quantity);
initial_jobs();
readJobdata();
HRRFschdulejob();
initial_jobs();
readJobdata();
HPF(jobs);
system(“pause”);
return 0;
}
四.实验结果
五.实验小结
通过实验发现FCFS算法比较容易实现,有利于长作业,不利于短作业。SJF算法易于实现,照顾了短进程,缩短了进程的等待时间,体现了短进程的优先原则。HRRF算法既照顾了长作业也照顾了先到达进程。
一、设计目的
银行家算法是避免死锁的一种重要方法,能够有效的在资源分配的过程中,对系统的安全性进行检测。
通过银行家算法设计与实现,可以加深对死锁的理解,掌握死锁的预防、避免、检测和解除的基本原理,重点掌握死锁的避免方法—银行家算法。初步具有研究、设计、编制和调试操作系统模块的能力。
二、要求
1、使用编程语言实现防止死锁的银行家算法,至少实现:
(1)实现动态进程的输入
(2)能够判断进程之间能否无死锁的运行下去,以及安全序列
(3)当各个进程又提出新的申请,资源是否能满足
(4)界面美观。
2、撰写课程设计报告
报告要有设计、实现、测试等过程。
三、实验代码
#include
using namespace std;
int n, m; //系统中进程总数n和资源种类总数m
int Available[100]; //资源可用总量
int Max[100][100]; //最大需求矩阵
int Allocation[100][100] = {0}; //当前给分配给每个进程的各种资源数量
int Need[100][100];//当前每个进程还需分配的各种资源数量
int Work[100]; //当前可分配的资源
bool Finish[100]; //进程是否结束
//显示功能
void show_function()
{
cout << “\n\n* 功能选择 *” << endl;
cout << “*1.显示当前资源情况 *” << endl;
cout << “*2.当前状态安全检查 *” << endl;
cout << “*3.请求资源分配 *” << endl;
cout << “*4.退出程序 *” << endl;
return;
}
//初始数据输入
void input()
{
cout << “请输入进程总数:” << endl;
cin >> n;
cout << “请输入资源种类总数:” << endl;
cin >> m;
cout << “请依次输入各种资源数量:” << endl;
for (int i = 0; i < m; i++)
{
cin >> Available[i];
}
for (int i = 0; i < n; i++)
{
cout << “*** 输入进程P” << i << “的初始信息 ***” << endl;
cout << “请输入该进程所需各资源的最大量:” << endl;
for (int j = 0; j < m; j++)
{
cin >> Max[i][j];
}
cout << “请输入该进程已分配各资源的数量:” << endl;
for (int j = 0; j < m; j++)
{
cin >> Allocation[i][j];
}
}
return;
}
//显示当前资源情况
void show()
{
//输出分配矩阵Allocation
cout << “\n*** 当前资源分配情况 " << endl;
cout << “进程”;
for (int i = 0; i < m; i++)
{
cout << “\t资源” << i;
}
cout << endl;
for (int i = 0; i < n; i++)
{
cout << “P” << i;
for (int j = 0; j < m; j++)
{
cout << “\t” << Allocation[i][j];
}
cout << endl;
}
//输出需求矩阵Need
cout << "\n 当前资源需求情况 " << endl;
cout << “进程”;
for (int i = 0; i < m; i++)
{
cout << “\t资源” << i;
}
cout << endl;
for (int i = 0; i < n; i++)
{
cout << “P” << i;
for (int j = 0; j < m; j++)
{
cout << “\t” << Need[i][j];
}
cout << endl;
}
//输出可利用资源量Available
cout << "\n 当前资源剩余情况 " << endl;
for (int i = 0; i < m; i++)
{
cout << “资源” << i << “\t”;
}
cout << endl;
for (int j = 0; j < m; j++)
{
cout << Available[j] << “\t”;
}
cout << endl;
//输出进程执行情况
cout << "\n 当前进程执行情况 ***” << endl;
for (int i = 0; i < n; i++)
{
cout << “进程” << i << “\t”;
}
cout << endl;
for (int j = 0; j < n; j++)
{
if (Finish[j])
{
cout << “true” << “\t”;
}
else
{
cout << “false” << “\t”;
}
}
cout << endl;
}
//判断是不是所有进程均已执行完
bool judge_end(bool *finish)
{
bool flag = 1;
for (int i = 0; i < m; i++)
{
if (finish[i] != true)
{
flag = 0;
break;
}
}
return flag;
}
//状态安全检查
void safety(int *result)
{
int ji = 1;
//初始化Work
for (int i = 0; i < m; i++)
{
Work[i] = Available[i];
}
//初始化finish,finish是在本次测试中标记是不是所有进程都执行完
bool finish[100];
for (int i = 0; i < n; i++)
{
finish[i] = Finish[i];
}
int flag1 = 0;
bool flag2 = 1;
for (int i = 0; i < n; i++)
{
//当循环新开始时,标记这次循环当前还没有结束任何进程
if (i == 0)
flag1 = 0;
//跳过已经完成的进程
if (finish[i] == true)
continue;
//Work与Need比较
int flag3 = 1;
for (int j = 0; j < m; j++)
{
if (Work[j] < Need[i][j])
{
flag3 = 0;
break;
}
}
//若资源不够则跳过这一进程
if (flag3 != 1)
{
//是不是本次循环进程一个都没能结束
if (i == n - 1 && flag1 != 1)
{
//分析一个都没能结束的原因
//是不是全部进程已经都执行完了
if (judge_end(finish))
break;
else
{
//存在没结束的进程但无法结束
flag2 = 0;
break;
}
}
continue;
}
else
{
//若资源够,则执行完该进程,释放该进程占用的资源
result[ji] = i;
ji++;
for (int j = 0; j < m; j++)
{
Work[j] = Work[j] + Allocation[i][j];
}
finish[i] = true;
flag1 = 1;//标记这一轮找到了可以执行完的进程
i = -1;//从头再开始遍历进程集合
}
}
result[0] = flag2;
return;
}
//资源分配
bool allocate(int number,int *request)
{
int flag = 1;
for (int i = 0; i < m; i++)
{
if (request[i] > Need[number][i])
{
flag = 0;
break;
}
}
if (flag == 0)
{
cout << “请求大于该进程还需要的资源量,请求不合法” << endl;
return 0;
}
flag = 1;
for (int i = 0; i < m; i++)
{
if (request[i] > Available[i])
{
flag = 0;
break;
}
}
if (flag == 0)
{
cout << “请求大于当前系统剩余的资源量,请求不合法” << endl;
return 0;
}
// 尝试分配
for (int i = 0; i < m; i++)
{
Need[number][i] = Need[number][i] - request[i];
Allocation[number][i] = Allocation[number][i] + request[i];
Available[i] = Available[i] - request[i];
}
//安全性判断
int result = (int)malloc(sizeof(int) * 101);
memset(result, -1, sizeof(int) * 101);
safety(result);
if (result[0])
{
cout << “存在此安全序列:”;
cout << “P” << result[1];
for (int i = 2;; i++)
{
if (result[i] == -1)
{
break;
}
cout << " --> P" << result[i];
}
cout << endl;
return 1;
}
else
{
cout << “根据安全性检查,本次分配不安全”<
for (int i = 0; i < m; i++)
{
Need[number][i] = Need[number][i] + request[i];
Allocation[number][i] = Allocation[number][i] - request[i];
Available[i] = Available[i] + request[i];
}
return 0;
}
}
void end(int number)
{
int flag = 1;
for (int i = 0; i < m; i++)
{
if (Need[number][i] != 0)
{
flag = 0;
break;
}
}
//若果这个进程已经不需要再分配资源了
//执行完该进程,释放已分配资源
if (flag == 1)
{
cout << “*** 进程P”<
for (int i = 0; i < m; i++)
{
Available[i] = Available[i] + Allocation[number][i];
Allocation[number][i] = 0;
}
}
}
int main()
{
//freopen(“in.txt”, “r”, stdin);
cout << “******************************” << endl;
cout << “*** 欢迎来到银行家算法 ***” << endl;
cout << “***1.显示当前资源情况 ***” << endl;
cout << “***2.当前状态安全检查 ***” << endl;
cout << “***3.请求资源分配 ***” << endl;
cout << “***4.退出程序 ***” << endl;
cout << “******************************\n” << endl;
memset(Finish, false, sizeof(Finish));
//初始数据输入
input();
//计算Need矩阵和剩余的可以利用资源Available
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
Need[i][j] = Max[i][j] - Allocation[i][j];
Available[j] = Available[j] - Allocation[i][j];
}
}
int flag;
while (true)
{
//功能选择
show_function();
cout << “请选择功能:”;
cin >> flag;
if (flag == 1)
{
//显示当前资源情况
//包括当前资源分配情况和资源剩余情况
show();
}
else if (flag == 2)
{
//当前状态安全检查
int result = (int)malloc(sizeof(int) * 101);
memset(result, -1, sizeof(int) * 101);
safety(result);
if (result[0] == 1)
{
cout << “存在此安全序列:”;
cout << “P” << result[1];
for (int i = 2;; i++)
{
if (result[i] == -1)
{
break;
}
cout << " --> P" << result[i];
}
cout << endl;
cout << “*** 此刻状态安全 ***” << endl;
}
else
{
cout << “*** 此刻状态不安全! " << endl;
}
}
else if (flag == 3)
{
//请求资源分配
int request = (int)malloc(sizeof(int) * 100);
int number;
cout << “请输入发出请求的进程:P”;
cin >> number;
cout << “请输入请求各资源的数量:” << endl;
for (int i = 0; i < m; i++)
{
cin >> request[i];
}
if (allocate(number, request))
{
cout << " 该分配安全,分配成功! " << endl;
//成功分配的进程,能完成的就完成,释放占用的资源
end(number);
}
else
{
cout << " 分配失败! ***” << endl;
}
}
else if (flag == 4)
{
//退出程序
cout << “成功退出!” << endl;
break;
}
}
return 0;
}
四.实验结果
五.实验小结
通过这次实验发现在银行家算法中主要是实现了显示当前资源情况、当前状态安全检查、请求资源分配等功能。我认为难点是在判断安全状态,如果思路不够清晰容易混乱。
(实验目的、实验原理、实验步骤、内容、程序代码、实验数据、结论等)
一、实验目的
1、详细了解系统之中是如何存储进程的。
2、通过实验加强对基于顺序搜索的动态分区分配算法的理解和掌握。
3、加深理解有关存储结构的概念。
4、主存的分配和回收的实现与主存储器的管理方式有关的,通过本实验帮助学生理解在可变分区管理方式下应怎样实现主存空间的分配和回收。
二、实验原理
1、动态分区分配是根据进程的实际需要,动态地址为之分配内存空间,而在分配时,须按照一定的分配算法,从空闲分区表或空闲分区链中选出一分区分配给该作业。
2、在本实验中运用了四种分配算法,分别是首次适应算法,循环首次适应算法,最坏适应算法,最佳适应算法。
三、实验代码
using Lab4;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Lab4
{
class Process
{
public string name;
public int needSpace;
public Process(string name, int needSpace)
{
this.name = name;
this.needSpace = needSpace;
}
}
class Space
{
private static string usedFlag = "1";
private static string freeFlag = ".";
public int id;//空间编号(从小到大排序)
public int startIndex;//空间开始索引
public int freeStartIndex;//空闲指针[空间内的相对位置0-空间大小]
public int freeSize;//空间块空闲大小
public List SpaceDetail;//空间详情
private List SpaceDetailNote;//【辅助变量】空间详情描述,便于观察分配结果
private int NoteStartIndex;//【辅助变量】空间块空闲大小
public Space(int id, int startIndex, int size)
{
this.id = id;
this.startIndex = startIndex;
freeStartIndex = 0;
freeSize = size;
SpaceDetail = new List(); SpaceDetailNote = new List(); NoteStartIndex = 0;
for (int i = 0; i < size; i++)
{
SpaceDetail.Add(freeFlag); SpaceDetailNote.Add(freeFlag);
}
}
public void useSpace(Process process)
{
for (int i = freeStartIndex; i < freeStartIndex + process.needSpace; i++)
{
SpaceDetail[i] = usedFlag;
}
freeSize -= process.needSpace;
freeStartIndex = SpaceDetail.Count - freeSize - 1;
SpaceDetailNote.RemoveRange(NoteStartIndex, process.needSpace); SpaceDetailNote.Insert(NoteStartIndex, process.name + "[" + process.needSpace + "]"); NoteStartIndex++;
}
public void printSpace()
{
for (int i = 0; i < SpaceDetail.Count; i++)
{
Console.Write(SpaceDetail[i]);
}
}
public void printSpaceNote()
{
for (int i = 0; i < SpaceDetailNote.Count; i++)
{
Console.Write(SpaceDetailNote[i]);
}
}
}
class RAM
{
public int size;//内存大小
public List spaceDetail;//内存块详情
public RAM(int[] spaceSizeArray)
{
size = 0;
spaceDetail = new List();
for (int i = 0; i < spaceSizeArray.Length; i++)
{
spaceDetail.Add(new Space(i, size, spaceSizeArray[i]));
size += spaceSizeArray[i];
}
}
public void printRAM(bool printNote = false)
{
//打印前将存储块从小到大排序
spaceDetail = spaceDetail.OrderBy(m => m.id).ToList();
Console.WriteLine("当前RAM状态如下: \n");
foreach (var space in spaceDetail)
{
space.printSpace();
Console.Write("|");
//Console.WriteLine(space.id + "[" + space.startIndex + "," + (space.startIndex + space.SpaceDetail.Count-1) + "]");
}
Console.WriteLine("\n");
if (printNote)
{
foreach (var space in spaceDetail)
{
space.printSpaceNote();
Console.Write("|");
//Console.WriteLine(space.id + "[" + space.startIndex + "," + (space.startIndex + space.SpaceDetail.Count-1) + "]");
}
Console.WriteLine("\n");
}
}
//首次适应算法
public bool FirstPartition(List processList)
{
Console.WriteLine("首次适应算法进行中...");
//默认分配成功次数
int succcefulCount = 0;
//遍历所有进程
for (int i = 0; i < processList.Count; i++)
{
//遍历所有空间块
for (int j = 0; j < spaceDetail.Count; j++)
{
//如果空间充足
if (spaceDetail[j].freeSize >= processList[i].needSpace)
{
//分配空间并转至处理下一进程
spaceDetail[j].useSpace(processList[i]);
succcefulCount += 1;
break;
}
}
}
return succcefulCount == processList.Count ? true : false;
}
//循环首次适应算法
public bool CycleFirstPartition(List processList)
{
Console.WriteLine("循环首次适应算法进行中...");
//记录上次空间块的位置和1个进程比较空间块的次数
int spaceIndex = 0, compareCount = 0;
//默认分配成功次数
int succcefulCount = 0;
//遍历所有进程
for (int i = 0; i < processList.Count; i++)
{
//切换到新进程时重置比较次数
compareCount = 0;
//循环遍历所有空间块
while (compareCount < spaceDetail.Count)
{
//如果比较了所有空间块则终止,防止死循环!
if (compareCount == spaceDetail.Count)
{
compareCount = spaceDetail.Count;//同时跳出第二层循环
break;
}
//取模运算,防止循环越界!
if (spaceIndex >= spaceDetail.Count)
{
spaceIndex = spaceIndex % spaceDetail.Count;
}
//如果空间充足
if (spaceDetail[spaceIndex].freeSize >= processList[i].needSpace)
{
//分配空间并转至处理下一进程
spaceDetail[spaceIndex].useSpace(processList[i]);
succcefulCount++;
spaceIndex++;//移动指针到下一空间
break;
}
spaceIndex++;//移动指针
}
}
return succcefulCount == processList.Count ? true : false;
}
//最佳适应算法
public bool BestPartition(List processList)
{
Console.WriteLine("最佳适应算法进行中...");
//默认分配成功次数
int succcefulCount = 0;
//遍历所有进程
for (int i = 0; i < processList.Count; i++)
{
//空间块排序(按剩余空间从小到大)
spaceDetail = spaceDetail.OrderBy(m => m.freeSize).ToList();
//取出空间访问顺序
List orders = (from t in spaceDetail select t.id).ToList();
//按访问顺序遍历所有空间块
for (int j = 0; j < orders.Count; j++)
{
int order = orders[j];
Space space = (from t in spaceDetail where t.id == order select t).FirstOrDefault();
//如果空间充足
if (space.freeSize >= processList[i].needSpace)
{
//分配空间并转至处理下一进程
spaceDetail[j].useSpace(processList[i]);
succcefulCount += 1;
break;
}
}
}
return succcefulCount == processList.Count ? true : false;
}
//最坏适应算法
public bool WorstPartition(List processList)
{
Console.WriteLine("最坏适应算法进行中...");
//默认分配成功次数
int succcefulCount = 0;
//遍历所有进程
for (int i = 0; i < processList.Count; i++)
{
//空间块排序(按剩余空间从大到小)
spaceDetail = spaceDetail.OrderByDescending(m => m.freeSize).ToList();
//取出空间访问顺序
List orders = (from t in spaceDetail select t.id).ToList();
//按访问顺序遍历所有空间块
for (int j = 0; j < orders.Count; j++)
{
int order = orders[j];
Space space = (from t in spaceDetail where t.id == order select t).FirstOrDefault();
//如果空间充足
if (space.freeSize >= processList[i].needSpace)
{
//分配空间并转至处理下一进程
spaceDetail[j].useSpace(processList[i]);
succcefulCount += 1;
break;
}
}
}
return succcefulCount == processList.Count ? true : false;
}
}
class Tool
{
public static void PrintProcessList(List processList)
{
Console.WriteLine("----------进程列表如下: \n");
for (int i = 0; i < processList.Count; i++)
{
Console.Write("进程名 " + processList[i].name + " 进程所需空间大小" + processList[i].needSpace+"\n");
}
Console.WriteLine("\n提示: . 表示未使用, 1 表示已被进程占用 \n");
}
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("----------动态分区分配算法----------- \n");
//初始化进程
List processList = new List();
processList.Add(new Process(“A”, 7));
processList.Add(new Process(“B”, 18));
processList.Add(new Process(“C”, 9));
processList.Add(new Process(“D”, 20));
//初始化内存
int[] spaceSizeArray = new int[] { 16, 16, 8, 32, 64, 32 };
//打印信息
Tool.PrintProcessList(processList);
var r1 = new RAM(spaceSizeArray); r1.printRAM();
if (r1.FirstPartition(processList))
{
r1.printRAM(true);
}
else
{
Console.Write("警告:RAM不足,部分进程未处理!!! \n");
r1.printRAM(true);
}
var r2 = new RAM(spaceSizeArray); r2.CycleFirstPartition(processList); r2.printRAM(true);
var r3 = new RAM(spaceSizeArray); r3.BestPartition(processList); r3.printRAM(true);
var r4 = new RAM(spaceSizeArray); r4.WorstPartition(processList); r4.printRAM(true);
Console.ReadLine();
}
}
四.实验结果
五.实验小结
通过这次实验加深了对动态分区分配算法的理解,进一步掌握了首次适应算法、循环首次适应 算法、最佳适应算法和最坏适应算法的实现方法。
一.实验目的
用高级语言模拟页面置换算法LRU,加深对LRU算法的认识。
实验原理
二.实验原理:当进程在CPU上运行时,如指令中涉及逻辑地址时,操作系统自动根据页表得到页号相关信息。
如果某一个页面被访问了,它很可能还要被访问;相反,如果它长时间不被访问,再最近未来是不大可能被访问的。
三.实验代码
#include
using namespace std;
class LinkStack{
private:
struct Node{
int elem;
struct Node* next;
struct Node* prev;
};
struct Node* head;
struct Node* tail;
public:
LinkStack(){
head=new struct Node;
tail=new struct Node;
head->next=NULL;
head->prev=NULL;
tail=head;
}
~LinkStack(){}
void push(int k){
struct Node* middle = new struct Node;
middle->elem=k;
tail->next=middle;
middle->prev=tail;
middle->next=NULL;
tail=middle;
}
void pop(){
if(tail==head){
cout<<“the stack is empty”;
}
else{
struct Node* middle=new struct Node;
middle=tail;
tail=tail->prev;
//tail->prev->next=tail;
tail->next=NULL;
free(middle);
}
}
void del(int k){
struct Node* ser = new struct Node;
ser=head;
while(ser=ser->next){
if(ser->elem==k){
ser->prev->next=ser->next;
ser->next->prev=ser->prev;
tail->next=ser;
ser->prev=tail;
ser->next=NULL;
tail=ser;
break;
}
}
}
bool findlink(int k){
struct Node* ser = new struct Node;
ser=head;
while(ser=ser->next){
if(ser->elem==k){
return true;
}
}
return false;
}
void print_structure(){
struct Node* ser=new struct Node;
ser=tail;
while(ser!=head){
cout<<"+--------------+\n";
cout<elem<prev;
}
}
int feedback(int k){
int level=1;
struct Node* ser=new struct Node;
ser=head;
while(ser=ser->next){
if(ser->elem==k){
return level;
}
level++;
}
}
int back_head(){
return head->next->elem;
}
};
int main()
{
int k;LinkStack s;
cout<<“请输入空闲的帧的数目:\n”;
int p;cin>>p;int sum=p;
int element[p];
while(11){
cout<<“以下输入一个引用串:”<
if(p>0){
cout<<“具有空闲帧\n”;
int flag=1;
for(int i=0;i
cout<<“当前引用串已经存在于页帧中,故无需请求调页\n”;
flag=0;break;
}
}
if(flag1){
for(int i=0;i
element[sum-p]=k;
cout<
p–;
}
}
else if(p
int flag=0;
for(int i=0;i
cout<<“该引用已经存在于页帧中,故无需进行页面置换\n”;
flag=1;break;
}
}
if(flag0){
int mind=1e6+10,j=0;
cout<<“没有空闲帧且该引用不存在于当前的页帧中,开始进行页面置换\n”;
for(int i=0;i
}
}
element[j]=k;
for(int i=0;i
}
if(!s.findlink(k)){
s.push(k);
}
else{
s.del(k);
}
}
}
}
四.实验结果
五.实验小结
通过实验了解了LRU算法的核心思想就是:因为无法预测各页面将来的使用情况,只能利用最近的过去作为最近的将来的近似。他的核心就在于manage函数,这个判断的顺序很重要。只要弄清楚判断顺序,整个问题就解决了。