操作系统实验全五个教学教材.docx
《操作系统实验全五个教学教材.docx》由会员分享,可在线阅读,更多相关《操作系统实验全五个教学教材.docx(36页珍藏版)》请在冰豆网上搜索。
操作系统实验全五个教学教材
操作系统试验指导
—.课程的性质、目的和任务
操作系统在整个计算机系统软件中占有中心地位。
其作用是对计算机系统进行统一的调度和管理,提供各种强有力的系统服务,为用户创造既灵活又方便的使用环境。
本课程是计算机及应用专业的一门专业主干课和必修课。
通过本课程的学习,使学生掌握操作系统的基本概念、设计原理及实施技术,具有分析操作系统和设计、实现、开发实际操作系统的能力。
二.实验的意义和目的
操作系统是计算机专业学生的一门重要的专业课程。
操作系统质量对整个计算机系统的性能和用户对计算机的使用有重大的影响。
一个优良的操作系统能极大地扩充计算机系统的功能,充分发挥系统中各种设备的使用效率,提高系统工作的可靠性。
由于操作系统涉及计算机系统中各种软硬件资源的管理,内容比较繁琐,具有很强的实践性。
要学好这门课程,必须把理论与实践紧密结合,才能取得较好的学习效果。
培养计算机专业的学生的系统程序设计能力,是操作系统课程的一个非常重要的环节。
通过操作系统上机实验,可以培养学生程序设计的方法和技巧,提高学生编制清晰、合理、可读性好的系统程序的能力,加深对操作系统课程的理解。
使学生更好地掌握操作系统的基本概念、基本原理、及基本功能,具有分析实际操作系统、设计、构造和开发现代操作系统的基本能力。
三.实验运行环境及上机前的准备
实验运行环境:
C语言编程环境
上机前的准备工作包括:
●按实验指导书要求事先编好程序;
●准备好需要输入的中间数据;
●估计可能出现的问题;
●预计可能得到的运行结果。
四.实验内容及安排
实验内容包括进程调度、银行家算法、页式地址重定位模拟,LRU算法模拟和先来先服务算法五个实验。
每个实验介绍了实习的目的要求、内容和方法。
实验一、进程调度试验
[目的要求]
用高级语言编写和调试一个进程调度程序,以加深对进程的概念及进程调度算法的理解.
[准备知识]
一、基本概念
1、进程的概念;
2、进程的状态和进程控制块;
3、进程调度算法;
二、进程调度
1、进程的状态
2、进程的结构——PCB
进程都是由一系列操作(动作)所组成,通过这些操作来完成其任务。
因此,不同的进程,其内部操作也不相同。
在操作系统中,描述一个进程除了需要程序和私有数据之外,最主要的是需要一个与动态过程相联系的数据结构,该数据结构用来描述进程的外部特性(名字、状态等)以及与其它进程的联系(通信关系)等信息,该数据结构称为进程控制块(PCB,ProcessControlBlock)。
进程控制块PCB与进程一一对应,PCB中记录了系统所需的全部信息、用于描述进程情况所需的全部信息和控制进程运行所需的全部信息。
因此,系统可以通过进程的PCB来对进程进行管理。
[试验内容]
设计一个有N个进程共行的进程调度程序。
进程调度算法:
采用最高优先数优先的调度算法(即把处理机分配给优先数最高的进程)和先来先服务算法。
每个进程有一个进程控制块(PCB)表示。
进程控制块可以包含如下信息:
进程名、优先数、到达时间、需要运行时间、已用CPU时间、进程状态等等。
进程的优先数及需要的运行时间可以事先人为地指定(也可以由随机数产生)。
进程的到达时间为进程输入的时间。
进程的运行时间以时间片为单位进行计算。
每个进程的状态可以是就绪W(Wait)、运行R(Run)、或完成F(Finish)三种状态之一。
就绪进程获得CPU后都只能运行一个时间片。
用已占用CPU时间加1来表示。
如果运行一个时间片后,进程的已占用CPU时间已达到所需要的运行时间,则撤消该进程,如果运行一个时间片后进程的已占用CPU时间还未达所需要的运行时间,也就是进程还需要继续运行,此时应将进程的优先数减1(即降低一级),然后把它插入就绪队列等待CPU。
每进行一次调度程序都打印一次运行进程、就绪队列、以及各个进程的PCB,以便进行检查。
重复以上过程,直到所要进程都完成为止。
调度算法的流程图如下:
进程调度源程序如下:
jingchendiaodu.cpp
#include"stdio.h"
#include
#include
#definegetpch(type)(type*)malloc(sizeof(type))
#defineNULL0
structpcb{/*定义进程控制块PCB*/
charname[10];
charstate;
intsuper;
intntime;
intrtime;
structpcb*link;
}*ready=NULL,*p;
typedefstructpcbPCB;
sort()/*建立对进程进行优先级排列函数*/
{
PCB*first,*second;
intinsert=0;
if((ready==NULL)||((p->super)>(ready->super)))/*优先级最大者,插入队首*/
{
p->link=ready;
ready=p;
}
else/*进程比较优先级,插入适当的位置中*/
{
first=ready;
second=first->link;
while(second!
=NULL)
{
if((p->super)>(second->super))/*若插入进程比当前进程优先数大,*/
{/*插入到当前进程前面*/
p->link=second;
first->link=p;
second=NULL;
insert=1;
}
else/*插入进程优先数最低,则插入到队尾*/
{
first=first->link;
second=second->link;
}
}
if(insert==0)first->link=p;
}
}
input()/*建立进程控制块函数*/
{
inti,num;
clrscr();/*清屏*/
printf("\n请输入进程号?
");
scanf("%d",&num);
for(i=0;i{
printf("\n进程号No.%d:
\n",i);
p=getpch(PCB);
printf("\n输入进程名:
");
scanf("%s",p->name);
printf("\n输入进程优先数:
");
scanf("%d",&p->super);
printf("\n输入进程运行时间:
");
scanf("%d",&p->ntime);
printf("\n");
p->rtime=0;p->state='w';
p->link=NULL;
sort();/*调用sort函数*/
}
}
intspace()
{
intl=0;PCB*pr=ready;
while(pr!
=NULL)
{
l++;
pr=pr->link;
}
return(l);
}
disp(PCB*pr)/*建立进程显示函数,用于显示当前进程*/
{
printf("\nqname\tstate\tsuper\tndtime\truntime\n");
printf("|%s\t",pr->name);
printf("|%c\t",pr->state);
printf("|%d\t",pr->super);
printf("|%d\t",pr->ntime);
printf("|%d\t",pr->rtime);
printf("\n");
}
check()/*建立进程查看函数*/
{
PCB*pr;
printf("\n****当前正在运行的进程是:
%s",p->name);/*显示当前运行进程*/
disp(p);
pr=ready;
printf("\n****当前就绪队列状态为:
\n");/*显示就绪队列状态*/
while(pr!
=NULL)
{
disp(pr);
pr=pr->link;
}
}
destroy()/*建立进程撤消函数(进程运行结束,撤消进程)*/
{
printf("\n进程[%s]已完成.\n",p->name);
free(p);
}
running()/*建立进程就绪函数(进程运行时间到,置就绪状态*/
{
(p->rtime)++;
if(p->rtime==p->ntime)
destroy();/*调用destroy函数*/
else
{
(p->super)--;
p->state='w';
sort();/*调用sort函数*/
}
}
main()/*主函数*/
{
intlen,h=0;
charch;
input();
len=space();
while((len!
=0)&&(ready!
=NULL))
{
ch=getchar();
h++;
printf("\nTheexecutenumber:
%d\n",h);
p=ready;
ready=p->link;
p->link=NULL;
p->state='R';
check();
running();
printf("\n按任一键继续......");
ch=getchar();
}
printf("\n\n进程已经完成.\n");
ch=getchar();}
实验二、银行家算法
(一)目的和要求
银行家算法是由Dijkstra设计的最具有代表性的避免死锁的算法。
本实验要求用高级语言编写一个银行家的模拟算法。
通过本实验可以对预防死锁和银行家算法有更深刻的认识。
(二)实验内容
1、设置数据结构
包括可利用资源向量(Availiable),最大需求矩阵(Max),分配矩阵(Allocation),需求矩阵(Need)
2、设计安全性算法
设置工作向量Work表示系统可提供进程继续运行可利用资源数目,Finish表示系统是否有足够的资源分配给进程
(三)实验环境
1、pc
2、vc++
(四)、程序源代码:
/*子函数声明*/
intIsprocessallover();//判断系统中的进程是否全部运行完毕
voidSystemstatus();//显示当前系统中的资源及进程情况
intBanker(int,int*);//银行家算法
voidAllow(int,int*);//若进程申请不导致死锁,用此函数分配资源
voidForbidenseason(int);//若发生死锁,则显示原因
/*全局变量*/
intAvailiable[3]={3,3,2};//初始状态,系统可用资源量
intMax[5][3]={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}};
//各进程对各资源的最大需求量
intAllocation[5][3]={{0,1,0},{2,0,0},{3,0,2},{2,1,1},{0,0,2}};
//初始状态,各进程占有资源量
intNeed[5][3]={{7,4,3},{1,2,2},{6,0,0},{0,1,1},{4,3,1}};
//初始状态时,各进程运行完毕,还需要的资源量
intover[5]={0,0,0,0,0};//标记对应进程是否得到所有资源并运行完毕
#include
/*主函数*/
voidmain()
{
intprocess=0;//发出请求的进程
intdecide=0;//银行家算法的返回值
intRequest[3]={0,0,0};//申请的资源量数组
intsourcenum=0;//申请的各资源量
/*判断系统中进程是否全部运行完毕*/
step1:
if(Isprocessallover()==1)
{
cout<<"系统中全部进程运行完毕!
";
return;
}
/*显示系统当前状态*/
Systemstatus();
/*人机交互界面*/
step2:
cout<<"\n输入发出请求的进程(输入“0”退出系统):
";
cin>>process;
if(process==0)
{
cout<<"放弃申请,退出系统!
";
return;
}
if(process<1||process>5||over[process-1]==1)
{
cout<<"系统无此进程!
\n";
gotostep2;
}
cout<<"此进程申请各资源(A,B,C)数目:
\n";
for(inth=0;h<3;h++)
{
cout<";
cin>>sourcenum;
Request[h]=sourcenum;
}
/*用银行家算法判断是否能够进行分配*/
decide=Banker(process,Request);
if(decide==0)
{
/*将此进程申请资源分配给它*/
Allow(process,Request);
gotostep1;
}
else
{
/*不能分配,显示原因*/
Forbidenseason(decide);
gotostep2;
}
}
/*子函数Isprocessallover()的实现*/
intIsprocessallover()
{
intprocessnum=0;
for(inti=0;i<5;i++)
{
/*判断每个进程是否运行完毕*/
if(over[i]==1)
processnum++;
}
if(processnum==5)
/*系统中全部进程运行完毕*/
return1;
else
return0;
}
/*子函数Systemstatus()的实现*/
voidSystemstatus()
{
cout<<"此刻系统中存在的进程:
\n";
for(inti=0;i<5;i++)
{
if(over[i]!
=1)
cout<<"P"<
}
cout<cout<<"此刻系统可利用资源(单位:
个):
\n";
cout<<"ABC\n";
for(inta=0;a<3;a++)
{
cout<}
cout<cout<<"此刻各进程已占有资源如下(单位:
个):
\n"
<<"ABC\n";
for(intb=0;b<5;b++)
{
if(over[b]==1)
continue;
cout<<"P"<
for(intc=0;c<3;c++)
cout<cout<}
cout<<"各进程运行完毕还需各资源如下(单位:
个):
\n"
<<"ABC\n";
for(intf=0;f<5;f++)
{
if(over[f]==1)
continue;
cout<<"P"<for(intg=0;g<3;g++)
cout<cout<}
}
/*子函数Banker(int,int&)的实现*/
intBanker(intp,int*R)
{
intnum=0;//标记各资源是否能满足各进程需要
intFinish[5]={0,0,0,0,0};//标记各进程是否安全运行完毕
intwork[5]={0,0,0,0,0};//用于安全检查
intAvailiableTest[3];//用于试分配
intAllocationTest[5][3];//同上
intNeedTest[5][3];//同上
/*判断申请的资源是否大于系统可提供的资源总量*/
for(intj=0;j<3;j++)
{
if(*(R+j)>Availiable[j])
/*返回拒绝分配原因*/
return1;
}
/*判断该进程申请资源量是否大于初始时其申明的需求量*/
for(inti=0;i<3;i++)
{
if(*(R+i)>Need[p-1][i])
/*返回拒绝原因*/
return2;
}
/*为检查分配的各数据结构赋初值*/
for(intt=0;t<3;t++)
{
AvailiableTest[t]=Availiable[t];
}
for(intu=0;u<5;u++)
{
for(intv=0;v<3;v++)
{
AllocationTest[u][v]=Allocation[u][v];
}
}
for(intw=0;w<5;w++)
{
for(intx=0;x<3;x++)
{
NeedTest[w][x]=Need[w][x];
}
}
/*进行试分配*/
for(intk=0;k<3;k++)//修改NeedTest[]
{
AvailiableTest[k]-=*(R+k);
AllocationTest[p-1][k]+=*(R+k);
NeedTest[p-1][k]-=*(R+k);
}
/*检测进程申请得到满足后,系统是否处于安全状态*/
for(intl=0;l<3;l++)
{
work[l]=AvailiableTest[l];
}
for(intm=1;m<=5;m++)
{
for(intn=0;n<5;n++)
{
num=0;
/*寻找用此刻系统中没有运行完的进程*/
if(Finish[n]==0&&over[n]!
=1)
{
for(intp=0;p<3;p++)
{
if(NeedTest[n][p]<=work[p])
num++;
}
if(num==3)
{
for(intq=0;q<3;q++)
{
work[q]=work[q]+AllocationTest[n][q];
}
Finish[n]=1;
}
}
}
}
for(intr=0;r<5;r++)
{
if(Finish[r]==0&&over[r]!
=1)
/*返回拒绝分配原因*/
return3;
}
return0;
}
/*子函数Allow(int,int&)的实现*/
voidAllow(intp,int*R)
{
cout<<"可以满足申请!
";
staticintovernum;
/*对进程所需的资源进行分配*/
for(intt=0;t<3;t++)
{
Availiable[t]=Availiable[t]-*(R+t);
Allocation[p-1][t]=Allocation[p-1][t]+*(R+t);
Need[p-1][t]=Need[p-1][t]-*(R+t);
}
/*分配后判断其是否运行完毕*/
overnum=0;
for(intv=0;v<3;v++)
{
if(Need[p-1][v]==0)
overnum++;
}
if(overnum==3)
{
/*此进程运行完毕,释放其占有的全部资源*/
for(intq=0;q<3;q++)
Availiable[q]=Availiable[q]+Allocation[p-1][q];
/*标记该进程运行完毕*/
over[p-1]=1;
cout<<"进程P"<
\n";
}
}
/*子函数Forbidenseason(int)的实现*/
voidForbidenseason(intd)
{
cout<<"不能满足申请,此进程挂起,原因为:
\n";
switch(d)
{
case1:
cout<<"申请的资源量大于系统可提供的资源量!
";break;
case2:
cout<<"申请的资源中有某种资源大于其声明的需求量!
";break;
case3:
cout<<"若满足申请,系统将进入不安全状态,可能导致死锁!
";
}
}
实验三、页式地址重定位模拟
一、实验目的:
1、用高级语言编写和调试模拟实现页式地址重定位。
2、加深理解页式地址重定位技术在多道程序设计中的作用和意义。
二、实验原理:
当进程在CPU上运行时,如指令中涉及逻辑地址时,操作系统自动根据页长得到页号和页内偏移,把页内偏移拷贝到物理地址寄存器,再根据页号,查页表,得到该页在内存中的块号,把块号左移页长的位数,写到物理地址寄存器。
三、实验内容:
1、设计页表结构
2、设计地址重定位算法
3、有良好的人机对话界面
四、程序源代码:
#definepagesize1024
#definepagetablelength64
/*系统页表*/
constintpagetable[pagetablelength]={0,42,29,15,45,31,44,43,
41,28,1,30,12,24,6,32,
14,27,13,46,7,33,10,22,
40,2,51,11,39,23,49,50,
26,16,25,4,47,17,3,48,
52,36,58,35,57,34,21,63,
5,37,18,8,62,56,20,54,
60,19,38,9,61,55,59,53};
#include
#include
voidmain()
{
intlogicaladdress=0;
intpagenum=0;
intw=0;
cout<<"系统页号对应块号情况(页号——>块号