操作系统实验指导书.docx
《操作系统实验指导书.docx》由会员分享,可在线阅读,更多相关《操作系统实验指导书.docx(57页珍藏版)》请在冰豆网上搜索。
操作系统实验指导书
《操作系统原理》
实验指导书
羊四清编写
适用专业:
计算机科学与技术
网络工程
湖南人文科技学院计算机科学技术系
2008年8月
前言
操作系统是计算机的核心和灵魂。
操作系统软件的设计对整个计算机的功能和性能起着至关重要的作用,所以此门课也是必不可少的,是面向计算机科学与技术、网络工程、软件工程等大多数计算机专业本科生开设的一门计算机专业课程。
操作系统是计算机系统的核心,《操作系统》课程是计算机科学与技术专业的重要必修课。
本课程的目的是使学生掌握现代计算机操作系统的基本原理、基本设计方法及实现技术,具有分析现行操作系统和设计、开发实际操作系统的基本能力。
操作系统实验是操作系统课程的重要组成部分,属于学科基础实验范畴。
作为与相关教学内容配合的实践性教学环节,应在操作系统理论课教学过程中开设。
操作系统是计算机科学与技术专业必修的专业基础课程,操作系统实验的作用是:
理解操作系统的设计和实现思路,掌握典型算法。
基本要求是:
理解进程的概念,理解死锁,掌握银行家算法;掌握请求页式存储管理的实现原理及页面置换算法。
学生应具有高级语言编程能力、具有数据结构等基础知识。
说明:
本实验指导书所提供的源程序均已在VC6.0下调试运行过.
实验一进程创建模拟
实验学时:
2
实验类型:
验证
实验要求:
必修
一、实验目的
1)理解进程创建相关理论;
2)掌握进程创建方法;
3)掌握进程相关数据结构。
二、实验内容
本实验针对操作系统中进程创建相关理论进行实验。
要求实验者输入实验指导书提供的代码并进行测试。
代码简化了进程创建的多个步骤和内容。
进程的树形结构采用广义二叉树的方式进行存储。
三、实验原理
1)进程控制块
为了描述和控制进程的运行,系统为每个进程定义了一个进程控制块(PCB),它是进程实体的一部分,是操作系统管理进程最重要的数据结构。
其主要包含四类信息:
(1)进程标识符
它唯一地标识一个进程。
通常包括进程号pid,父进程号ppid和用户号uid。
(2)处理机状态
处理器的状态通常由处理机的各种寄存器中的内容组成。
PCB存放中断(阻塞,挂起)时的各寄存器值,当该进程重新执行时,可以从断点处恢复。
主要包括:
a)通用寄存器;
b)指令计数器;
c)程序状态字PSW;
d)用户栈指针。
(3)进程调度信息
a)进程状态;
b)进程优先级(用于描述优先使用cpu级别的一个整数,高优先级的进程先得到cpu,通常情况下,优先值越小优先级越高);
c)其它信息(等待时间、总执行时间等);
d)事件(等待原因)。
(4)进程控制信息
a)程序和数据的地址(程序在内存和外存中的首址);
b)进程同步和通信机制;
c)资源列表(进程除CPU以外的所有资源);
d)链接指针(进程队列中指向下一个进程的PCB首址)。
2)进程创建流程
(1)申请空白PCB
为新进程申请获得唯一的数字标识符,并从PCB集合中索取一个空白PCB。
如果无空白PCB,可以创建一个新的PCB。
在本实验中,每次动态创建PCB。
(2)为新进程分配资源
为新进程分配内存空间和栈空间。
(3)初始化进程控制块
a)初始化标识信息;
b)初始化处理机状态信息;
c)初始化处理机控制信息。
(4)将新进程插入就绪队列
P1
P2
P3
P4
P5
P6
P7
P8
P9
P10
P11
P12
3)进程树
图1-1进程树
进程树用于描述进程家族关系,如图1-1中可以看出,进程P1创建了进程P2、P3、P4、P5,而P2又创建了P6、P7、P8……。
在进程创建过程中,需要对每一个新增加的进程加入到进程树中,有了清晰的父子关系,可以使资源继承或进程删除等操作变得很方便。
4)进程总链
它是一个PCB链表,每一个新创建的进程必须把其PCB放入总链中,该总链可以对破坏的进程树进行修复,也方便PCB查找。
四、程序清单
1.basic.h文件
#ifndefbasic_h
#include
#include
#include
#definebasic_h
char*errormsg[256];
//processcontrolblock
structpcb
{
intpid;//processid
intppid;//parentprocessid
intprio;//priority
intstate;//state
intlasttime;//lastexecutetime
inttottime;//totleexecutetime
};
//processnode
structpnode
{
pcb*node;
pnode*sub;
pnode*brother;
pnode*next;
};
//信号量
structsemphore{
charname[5];//名称
intcount;//计数值
intcurpid;//当前进程id
pnode*wlist;//等待链表
};
#definegeterror(eno)printf("%s\n",errormsg[eno])
voidiniterror()
{
errormsg[0]=(char*)malloc(20);
errormsg[0]="errorcommand!
";
errormsg[1]=(char*)malloc(20);
errormsg[1]="errorparameter!
";
}
//getasubstringinstrings
char*substr(char*s,intstart,intend)
{
char*s1;
intlen=strlen(s);
if(start<0||end>=len||start>end)
returnNULL;
s1=(char*)malloc(end-start+2);
for(inti=0;i<=end-start;i++)
s1[i]=s[i+start];
s1[i]='\0';
returns1;
}
//findthelocationofcinstrings
intinstr(char*s,charc)
{
unsignedi;
for(i=0;iif(s[i]==c)
returni;
return-1;
}
//changethestringtoarraydata
int*strtoarray(char*s)
{
int*a,count,x1;
unsignedinti;
charc,*s1,*s2;
if(!
s)
{
printf("stringcan'tbenull!
\n");
returnNULL;
}
count=0;
s1=s;
for(i=0;iif(s1[i]==',')
count++;
count++;
a=(int*)malloc(count);
c=',';
for(i=0;i{
x1=instr(s1,c);
if(x1>=0)
s2=substr(s1,0,x1-1);
else
s2=s1;
a[i]=atoi(s2);
if(c==',')
s1=substr(s1,x1+1,strlen(s1)-1);
}
returna;
}
#endif
2、源程序
#include"basic.h"
pnode*proot;//systemprocesstreeroot
pnode*plink;//systemprocesslinkhead
//createprocess
intcreatepc(int*para)
{
//addyourcodehere
pnode*p,*p1,*pp;
intpflag;
pflag=0;
for(p=plink;p;p=p->next)
{
if(p->node->pid==para[0])//checkifthispidisalreadyexist
{
printf("pid%disalreadyexist!
\n",para[0]);
return-1;
}
if(p->node->pid==para[1])//findparentpcb
{
pflag=1;
pp=p;
}
}
if(!
pflag)
{
printf("parentid%disnotexist!
\n",para[1]);
return-2;
}
//initnewpcb
p1=newpnode;
p1->node=newpcb;
p1->node->pid=para[0];
p1->node->ppid=para[1];
p1->node->prio=para[2];
p1->sub=NULL;
p1->next=NULL;
p1->brother=NULL;
//addtoprocesstree
if(!
pp->sub)
pp->sub=p1;
else
{
for(p=pp->sub;p->brother;p=p->brother);
p->brother=p1;
}
//addtoprocesslink
for(p=plink;p->next;p=p->next);
p->next=p1;
return0;
}
//showprocessdetail
voidshowdetail()
{
//addyourcodehere
pnode*p,*p1;
p=plink;
for(;p;)//printallpcbinfo
{
printf("%d(prio%d):
",p->node->pid,p->node->prio);
p1=p->sub;
for(;p1;)//printsubpcb
{
printf("%d(prio%d)",p1->node->pid,p1->node->prio);
p1=p1->brother;
}
printf("\n");
p=p->next;
}
printf("\n");
}
//don'tchange
voidmain()
{
initerror();
shortcflag,pflag;
charcmdstr[32];
proot=newpnode;
proot->node=newpcb;
proot->node->pid=0;
proot->node->ppid=-1;
proot->node->prio=0;
proot->next=NULL;
proot->sub=NULL;
proot->brother=NULL;
plink=proot;
for(;;)
{
cflag=0;
pflag=0;
printf("cmd:
");
scanf("%s",cmdstr);
if(!
strcmp(cmdstr,"exit"))//exittheprogram
break;
if(!
strcmp(cmdstr,"showdetail"))
{
cflag=1;
pflag=1;
showdetail();
}
else
{
int*para;
char*s,*s1;
s=strstr(cmdstr,"createpc");//createprocess
if(s)
{
cflag=1;
para=(int*)malloc(3);
//getparameter
s1=substr(s,instr(s,'(')+1,strlen(s)-2);//getparamstring
para=strtoarray(s1);//getparameter
createpc(para);//createprocess
pflag=1;
}
}
if(!
cflag)
geterror(0);
else
if(!
pflag)
geterror
(1);
}
}
五、实验步骤
输入实验提供的代码后,可以输入createpc命令创建进程,输入showdetail显示每个进程及其子进程的信息,测试命令解释如下:
1)createpc创建进程命令。
参数:
1、pid(进程id)2、ppid(父进程id)3、prio(优先级)。
示例:
createpc(1,0,1)。
创建一个进程,其进程号为1,父进程号为0,优先级为1.
createpc(2,1,2)。
创建一个进程,其进程号为2,父进程号为1,优先级为2。
2)showdetail显示进程信息命令。
3)exit退出命令行。
六、思考题
1)进程创建的核心内容是什么?
2)该设计和实际的操作系统进程创建相比,缺少了哪些步骤?
实验二进程撤销模拟
实验学时:
2
实验类型:
验证
实验要求:
必修
一、实验目的
1)理解进程撤销相关理论;
2)掌握进程撤销流程。
二、实验内容
本实验针对操作系统中进程撤销相关理论进行实验。
要求实验者设计一个程序,该程序可模拟撤销多个进程及其子孙进程。
1)采用动态或静态方法生成一颗进程树(进程数目≥20);
2)设计进程撤销算法;
3)实现进程撤销函数,采用级联方式撤销;
4)可动态撤销进程;
5)可动态观察进程树的情况;
6)测试程序并得到正确结果。
三、实验原理
1)进程创建流程
(1)从PCB链中找到该进程的PCB,从中读出该进程的状态;
(2)如果该进程处于执行状态,则终止该进程并置调度标志为真;
(3)若该进程有子孙进程,需要撤销其子孙进程;
(4)释放该进程占有的资源;
(5)从PCB链中移出该进程的PCB。
2)进程子树的删除
对于已经创建的进程树(可以参考实验1创建进程),在删除的时候,首先需要考虑把该进程及其子孙从整棵树中脱离出来,这样才不会破坏整棵树的完整性。
3)进程总链元素的删除
对于进程树种撤销的所有进程,必须在进程总链中进行删除。
四、思考题
1)进程撤销的核心内容是什么?
2)进程总链在进程撤销过程中有什么作用?
实验三P、V原语的模拟实现
实验学时:
2
实验类型:
验证
实验要求:
必修
一、实验目的
1)理解信号量相关理论;
2)掌握记录型信号量结构;
3)掌握P、V原语实现机制。
二、实验内容
本实验针对操作系统中信号量相关理论进行实验,要求实验者输入实验指导书提供的代码并进行测试。
代码主要模拟信号量的P操作(down)和V操作(up)。
1)信号量
信号量也称为信号锁,主要应用于进程间的同步和互斥,在用于互斥时,通常作为资源锁。
信号量通常通过两个原子操作dwon(P)和up(V)来访问。
dwon操作使信号量的值+1,up操作使信号量的值-1。
2)记录型信号量
记录型信号量采用了“让权等待”的策略,存在多个进程等待访问同一临界资源的情况,所以记录型信号量需要一个等待链表来存放等待该信号量的进程控制块或进程号。
在本实验中,使用记录型信号量。
三、实验要求
1)输入给定代码;
2)进行功能测试并得出正确结果。
3)分析dwon和up函数功能模块;
4)在实验报告中画出dwon和up函数流程图;
5)撰写实验报告。
四、程序清单
#include"basic.h"
semphoresem[5];//deinfe5semphores
pnode*pr[20];//define0-19total20process
//downoperation
voiddown(char*sname,intpid)
{
intfflag,pflag;
pnode*p,*p1;
semphore*s;
fflag=0;
pflag=0;
for(inti=0;i<5;i++)
if(!
strcmp(sem[i].name,sname))//findsemaphorebyname
{
s=&sem[i];
fflag=1;
break;
}
for(i=0;i<20;i++)//findpcbbypid
if(pr[i]->node->pid==pid)
{
p1=pr[i];
pflag=1;
break;
}
if(!
fflag)//semaphoreisnotexist
{
printf("thesemphore'%s'isnotexist!
\n",sname);
return;
}
if(!
pflag)//pidisnotexist
{
printf("theprocess'%d'isnotexist!
\n",pid);
return;
}
s->count--;//semaphore!
svalue-1
if(s->count>=0)//thispcbgetthesemaphore
s->curpid=p1->node->pid;
else
{
if(s->wlist)//thelinkisnotNULL,addthepcbtothelast
{
for(p=s->wlist;p->next;p=p->next);
p->next=p1;
}
else//thispcbisthefirstpcbbeaddedtothedownlist
s->wlist=p1;
}
}
//upoperation
voidup(char*sname)
{
intfflag=0;
for(inti=0;i<5;i++)
if(!
strcmp(sem[i].name,sname))//findthesemaphorebyname
{
fflag=1;
break;
}
if(fflag)//findit
{
sem[i].count++;
if(sem[i].wlist)//thereareprocessesinthedownlist
{
sem[i].curpid=sem[i].wlist->node->pid;
sem[i].wlist=sem[i].wlist->next;
}
}
else
printf("thesemphore'%s'isnotexist!
\n",sname);
}
//showsemphoreinfomation
voidshowdetail()
{
inti;
pnode*p;
printf("\n");
for(i=0;i<5;i++)
{
if(sem[i].count<=0)
{
printf("%s(current_process%d):
",sem[i].name,sem[i].curpid);
p=sem[i].wlist;
while(p)
{
printf("%5d",p->node->pid);
p=p->next;
}
}
else
printf("%s:
",sem[i].name);
printf("\n");
}
}
/***************************************************************/
voidinit()
{
//initsemaphore
strcat(sem[0].name,"s0");
strcat(sem[1].name,"s1");
strcat(sem[2].name,"s2");
strcat(sem[3].name,"s3");
strcat(sem[4].name,"s4");
for(inti=0;i<5;i++)
{
sem[i].wlist=NULL;
sem[i].count=1;
}
//initprocess
for(i=0;i<20;i++)
{
pr[i]=newpnode;
pr[i]->node=newpcb;
pr[i]->node->pid=i;
pr[i]->brother=NULL;
pr[i]->next=NULL;
pr[i]->sub=NULL;
}
}
voidmain()
{
shortcflag,pflag;
charcmdstr[32];
char*s,*s1,*s2;
initerror();
init();
for(;;)
{
cflag=0;
pflag=0;
printf("cmd:
");
scanf("%s",cmdstr);
if(!
strcmp(cmdstr,"exit"))//exittheprogram
break;
if(!
strcmp(cmdstr,"showdetail"))
{