操作系统实验指导书文档格式.docx
《操作系统实验指导书文档格式.docx》由会员分享,可在线阅读,更多相关《操作系统实验指导书文档格式.docx(57页珍藏版)》请在冰豆网上搜索。
![操作系统实验指导书文档格式.docx](https://file1.bdocx.com/fileroot1/2023-2/3/cc710d38-1fec-48a6-8596-dc5a2ee3ad73/cc710d38-1fec-48a6-8596-dc5a2ee3ad731.gif)
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<
stdio.h>
string.h>
stdlib.h>
#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;
strlen(s);
if(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"
);
}
count=0;
s1=s;
strlen(s1);
if(s1[i]=='
'
)
count++;
a=(int*)malloc(count);
c='
count;
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
pid%disalreadyexist!
para[0]);
pid==para[1])//findparentpcb
pflag=1;
pp=p;
pflag)
parentid%disnotexist!
para[1]);
return-2;
//initnewpcb
p1=newpnode;
p1->
node=newpcb;
pid=para[0];
ppid=para[1];
prio=para[2];
sub=NULL;
next=NULL;
brother=NULL;
//addtoprocesstree
if(!
pp->
sub)
pp->
sub=p1;
else
for(p=pp->
sub;
p->
brother;
brother);
p->
brother=p1;
//addtoprocesslink
for(p=plink;
next;
next);
next=p1;
return0;
//showprocessdetail
voidshowdetail()
pnode*p,*p1;
p=plink;
for(;
)//printallpcbinfo
%d(prio%d):
p->
pid,p->
prio);
p1=p->
p1;
)//printsubpcb
%d(prio%d)"
p1->
pid,p1->
p1=p1->
p=p->
//don'
tchange
voidmain()
initerror();
shortcflag,pflag;
charcmdstr[32];
proot=newpnode;
proot->
pid=0;
ppid=-1;
prio=0;
plink=proot;
{
cflag=0;
pflag=0;
printf("
cmd:
scanf("
%s"
cmdstr);
if(!
strcmp(cmdstr,"
exit"
))//exittheprogram
break;
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);
pflag=1;
}
cflag)
geterror(0);
else
if(!
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)该设计和实际的操作系统进程创建相比,缺少了哪些步骤?
实验二进程撤销模拟
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原语的模拟实现
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)撰写实验报告。
semphoresem[5];
//deinfe5semphores
pnode*pr[20];
//define0-19total20process
//downoperation
voiddown(char*sname,intpid)
{
intfflag,pflag;
semphore*s;
fflag=0;
5;
i++)
strcmp(sem[i].name,sname))//findsemaphorebyname
{
s=&
sem[i];
fflag=1;
break;
}
20;
i++)//findpcbbypid
if(pr[i]->
pid==pid)
p1=pr[i];
pflag=1;
fflag)//semaphoreisnotexist
{
thesemphore'
%s'
isnotexist!
sname);
return;
}
pflag)//pidisnotexist
theprocess'
%d'
pid);
s->
count--;
//semaphore!
svalue-1
if(s->
count>
=0)//thispcbgetthesemaphore
curpid=p1->
pid;
else
wlist)//thelinkisnotNULL,addthepcbtothelast
for(p=s->
wlist;
p->
}
else//thispcbisthefirstpcbbeaddedtothedownlist
s->
wlist=p1;
//upoperation
voidup(char*sname)
intfflag=0;
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->
sem[i].wlist=sem[i].wlist->
else
}
//showsemphoreinfomation
voidshowdetail()
inti;
pnode*p;
if(sem[i].count<
=0)
printf("
%s(current_process%d):
"
sem[i].name,sem[i].curpid);
p=sem[i].wlist;
while(p)
{
printf("
%5d"
pid);
p=p->
}
%s:
sem[i].name);
/***************************************************************/
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"
sem[i].wlist=NULL;
sem[i].count=1;
//initprocess
pr[i]=newpnode;
pr[i]->
pid=i;
voidmain()
char*s,*s1,*s2;
init();
)
cflag=0;
scanf("
))//exittheprogram
))