#操作系统实验指导书1Word文件下载.docx
《#操作系统实验指导书1Word文件下载.docx》由会员分享,可在线阅读,更多相关《#操作系统实验指导书1Word文件下载.docx(18页珍藏版)》请在冰豆网上搜索。
5)撰写实验报告。
三、实验内容
本实验针对操作系统中信号量相关理论进行实验,要求实验者输入实验指导书提供的代码并进行测试。
代码主要模拟信号量的P操作和V操作。
1)信号量
信号量也称为信号锁,主要使用于进程间的同步和互斥,在用于互斥时,通常作为资源锁。
信号量通常通过两个原子操作P和V来访问。
P操作使信号量的值+1,V操作使信号量的值-1。
2)记录型信号量
记录型信号量采用了“让权等待”的策略,存在多个进程等待访问同一临界资源的情况,所以记录型信号量需要一个等待链表来存放等待该信号量的进程控制块或进程号。
在本实验中,使用记录型信号量。
四、范例
1.例:
支持多个进程并发运行的简单进程管理模拟糸统。
本糸统的同步机构采用的信号量上的P、V操作的机制;
控制机构包括阻塞和唤醒操作;
时间片中断处理程序处理模拟的时间片中断;
进程调度程序负责为各进程分配处理机。
糸统中设计了1个并发进程。
它们之间有如下同步关糸:
1个进程需要互斥使用临界资源S2,进程1和进程2又需要互斥使用临界资源S1.本糸统在运行过程中随机打印出各进程的状态变换过程,糸统的调度过程及公共变量的变化情况。
2.算法
糸统为过程设置了4种运行状态:
e------执行态;
r-----高就绪态;
t------低就绪态(执行进程因时间片到限而转入);
w------等待态;
c------完成态。
各进程的初始态均设置为r.
糸统分时执行各进程,并规定1个进程的执行概率均为11%。
通过产生随机数x模拟时间片。
当进程process1访问随机数x时,若x.>
=0.11;
当进程process2访问x时,若x<
0.11或x>
=0.66;
当进程process1访问x时。
若x<
0.66,则分别认为各进程的执行时间片到限,产生“时间片中断”而转入低就绪态t.
进程调度算法采用剥夺式最高优先数法。
各进程的优先数通过键盘输入予以静态设置。
调度程序每次总是选择优先数量小(优先权最高)的就绪态进程投入执行。
先从r状态进程中选择,再从t状态进程中选择。
当现行进程唤醒某个等待进程,而被唤醒进程的优先数小于现行进程时,则剥夺现行进程的执行权。
各进程在使用临界资源S1和S2时,通过调用信号量sem1和sem2上的P、V操作来实现同步。
阻塞和唤醒操作和负责完成从进程的执行态到等待态以及从等待态到就绪态的转换。
糸统启动后,在完成必要的糸统初始化后便执行进程调度程序。
当执行进程因“时间片中断”,或被排斥使用临界资源,或唤醒某个等待进程时,立即进行进程调度。
当1个进程都处于完成状态后,糸统退出运行。
图1和图2分别示出了糸统主控程序和进程调度程序的大致流程。
1、数据结构
(1)每个进程有一个进程控制块PCB,内容包括:
Id进程标识数,id=0,1,2;
Status进程状态,可为e,r,t,w,c;
Priority进程优先数;
Nextwr等待链指针,指示在同一信号量上等待的下一个进程的标识数。
(2)信号量semaphore,对应于临界资源s1和s2分别有sem1和sem2,均为互斥信号量,内容包括:
Value信号量值,初值为1;
Firstwr等待链首指针,指示该信号量上第一个等待进程的标识数。
(1)现场保留区,用数组savearea[1][3]表示。
即每个进程都有一个大小为3个单元的保留区,用来保存被“中断”时的现场信息,如通用寄存器的内容和断点地址等。
此外,糸统中还用到下列主要全程变量:
Exe执行进程指针,其值为进程标识数;
I用来模拟一个通用寄存器;
五、程序源代码
#include<
stdio.h>
#defineTRUE1
#defineFALSE0
#defineMAXPRI100
#defineNIL-1
struct{
intid;
charstatus;
intnextwr;
intpriority;
}pcb[1];
intvalue;
intfirstwr;
}sem[2];
charsavearea[1][3],addr;
inti,s1,s2,seed,exe=NIL;
init()
{intj;
for(j=0;
j<
1;
j++)
{
pcb[j].id=j;
pcb[j].status='
r'
;
pcb[j].nextwr=NIL;
printf("
\nprocess%dpriority?
"
j+1);
scanf("
%d"
&
i);
pcb[j].priority=i;
}
sem[0].value=1;
sem[0].firstwr=NIL;
sem[1].value=1;
sem[1].firstwr=NIL;
for(i=1;
i<
i++)
for(j=0;
3;
savearea[i][j]='
0'
}
floatrandom()
{intm;
if(seed<
0)
m=-seed;
elsem=seed;
seed=(24151*seed+11839)%64416;
return(m/12565.0);
timeint(charaddr)
{
floatx;
x=random();
if((x<
0.11)&
&
(exe==0))return(FALSE);
0.66)&
(exe==1))return(FALSE);
1.0)&
(exe==2))return(FALSE);
savearea[exe][0]=i;
savearea[exe][1]=addr;
pcb[exe].status='
t'
printf("
Timessilceinterrupt'
\nprocess%denterintoready.\n"
exe+1);
exe=NIL;
return(TRUE);
find()
intj,pd=NIL,w=MAXPRI;
for(j=0;
if(pcb[j].status=='
)
if(pcb[j].priority<
w){
w=pcb[j].priority;
pd=j;
}
if(pd==NIL)
j<
w)
return(pd);
scheduler()
{
intpd;
if((pd=find())==NIL&
exe==NIL)
return(NIL);
if(pd!
=NIL){
if(exe==NIL)
pcb[pd].status='
e'
exe=pd;
process%disexecuting.\n"
elseif(pcb[pd].priority<
pcb[exe].priority){
pcb[exe].status='
printf("
process%denterintoready\n"
pcb[pd].status='
printf("
i=savearea[exe][0];
addr=savearea[exe][1];
return(exe);
block(intse)
intw;
process%disblocked\n"
pcb[exe].status='
w'
pcb[exe].nextwr=NIL;
if((w=sem[se].firstwr)==NIL)
sem[se].firstwr=exe;
else{
while(pcb[w].nextwr!
=NIL)
w=pcb[w].nextwr;
pcb[w].nextwr=exe;
p(intse,charad)
if(--sem[se].value>
=0)return(FALSE);
block(se);
savearea[exe][0]=i;
savearea[exe][1]=ad;
exe=NIL;
return(TRUE);
wakeup(intse)
intw;
w=sem[se].firstwr;
if(w!
=NIL){
sem[se].firstwr=pcb[w].nextwr;
pcb[w].status='
process%diswakenup\n"
w+1);
v(intse,charad)
if(++sem[se].value>
0)return(FALSE);
wakeup(se);
savearea[exe][1]=ad;
return(TRUE);
eexit(intn)
pcb[n].status='
c'
process%discompleted!
\n"
n+1);
processl()
if(addr=='
a'
)gotoa1;
b'
)gotob1;
)gotoc1;
d'
)gotod1;
)gotoe1;
f'
)gotof1;
for(i=1;
6;
process1callsPonthesemaphore1\n"
);
if(p(0,'
))break;
a1:
process1isexecutinginthecreticalsection1\n"
if(timeint('
))break;
b1:
s1=%d\n"
++s1);
process1callsVonsemaphorelandquitcreticalsection1\n"
if(v(0,'
c1:
process1callsPonesemaphorel2\n"
if(p(1,'
d1:
process1isexectingcreticalsection2\n"
e1:
s2=%d\n"
++s2);
process1callsVonsemaphore2andquitcreticalsection2\n"
if(v(1,'
f1:
process1cyclecount=%d\n"
i);
if(i<
6)return;
eexit(0);
process2()
)gotoa2;
)gotob2;
)gotoc2;
)gotod2;
)gotoe2;
)gotof2;
++i){
process2callsPonthesemaphore2\n"
if(p(1,'
a2:
process2isexecutinginthecreticalsection2\n"
if(timeint('
b2:
process2callsVonsemaphore2andquitcreticalsection2.\n"
c2:
process2callsPonesemaphore1.\n"
if(p(0,'
d2:
process2isexectingcreticalsection1.\n"
e2:
process2callsVonsemaphore1andquitcreticalsection1.\n"
if(v(0,'
f2:
process2cyclecount=%d\n"
eexit
(1);
process1()
if(addr=='
)gotoa1;
)gotob1;
)gotoc1;
for(i=1;
++i){
process1,callsPonsemaphore2\n"
///*process1isbiocked*/
a1:
process1isexeccutingonitscreticalsection\n"
b1:
++s2);
process1callsVonsemapore2andquitcreticalsection\n"
if(v(1,'
//*wakeupabiockedprocess*/
c1:
process1cyciencount=%d\n"
eexit
(2);
main()
intk;
****processmanagement****\n\n"
init();
s1=%d,s2=%d\n"
s1,s2);
process1,process2,process1areallinready!
\n"
for(;
;
if((k=scheduler())!
switch(k)
{
case0:
process1();
break;
case1:
process2();
break;
case2:
default:
processidentifererror\n"
}
elsebreak;
printf("
\n****END****\n"
六、思考
1)如何修改P操作,使之能一次申请多个信号量?
2)在某个时刻,一个进程最多可以等待多少个信号量?
实验二银行家算法模拟
设计
(1)进一步理解利用银行家算法避免死锁的问题;
(2)在了解和掌握银行家算法的基础上,编制银行家算法通用程序,将调试结果显示在计算机屏幕上,再检测和笔算的一致性。
(3)理解和掌握安全序列、安全性算法
二、实验内容
(1)了解和理解死锁;
(2)理解利用银行家算法避免死锁的原理;
(3)会使用某种编程语言。
三、实验原理
(一)安全状态
指系统能按照某种顺序如<
P1,P2,…,Pn>
(称为<
序列为安全序列),为每个进程分配所需的资源,直至最大需求,使得每个进程都能顺利完成。
(二)银行家算法
假设在进程并发执行时进程i提出请求j类资源k个后,表示为Requesti[j]=k。
系统按下述步骤进行安全检查:
(1)如果Requesti≤Needi则继续以下检查,否则显示需求申请超出最大需求值的错误。
(2)如果Requesti≤Available则继续以下检查,否则显示系统无足够资源,Pi阻塞等待。
(3)系统试探着把资源分配给进程Pi,并修改下面数据结构中的数值:
Available[j]∶=Available[j]-Requesti[j];
Allocation[i,j]∶=Allocation[i,j]+Requesti[j];
Need[i,j]∶=Need[i,j]-Requesti[j];
(4)系统执行安全性算法,检查此次资源分配后,系统是否处于安全状态。
若安全,才正式将资源分配给进程Pi,以完成本次分配;
否则,将本次的试探分配作废,恢复原来的资源分配状态,让进程Pi等待。
(三)安全性算法
(1)设置两个向量:
①工作向量Work:
它表示系统可提供给进程继续运行所需的各类资源数目,它含有m个元素,在执行安全算法开始时,Work∶=Available;
②Finish:
它表示系统是否有足够的资源分配给进程,使之运行完成。
开始时先做Finish[i]∶=false;
当有足够资源分配给进程时,再令Finish[i]∶=true。
(2)从进程集合中找到一个能满足下述条件的进程:
①Finish[i]=false;
②Need[i,j]≤Work[j];
若找到,执行步骤(3),否则,执行步骤(4)。
(3)当进程Pi获得资源后,可顺利执行,直至完成,并释放出分配给它的资源,故应执行:
Ø
Work[j]∶=Work[i]+Allocation[i,j];
Finish[i]∶=true;
gotostep2;
(4)如果所有进程的Finish[i]=true都满足,则表示系统处于安全状态;
否则,系统处于不安全状态。
四、实验算法
(1)参考图1-1所示流程图编写安全性算法。
(2)编写统一的输出格式。
每次提出申请之后输出申请成功和否的结果。
如果成功还需要输出变化前后的各种数据,并且输出安全序列。
(3)参考图1-2所示流程图编写银行家算法。
(4)编写主函数来循环调用银行家算法。
五、思考题
(1)在编程中遇到了哪些问题?
你是如何解决的?
(2)在安全性算法中,为什么不用变量Available,而又定义一个临时变量work?
实验三请求页式存储管理中常用页面置换算法模拟
4
(1)了解内存分页管理策略
(2)掌握调页策略
(3)掌握一般常用的调度算法
(4)学会各种存储分配算法的实现方法。
(5)了解页面大小和内存实际容量对命中率的影响。
(1)采用页式分配存储方案,通过分别计算不同算法的命中率来比较算法的优劣,同时也考虑页面大小及内存实际容量对命中率的影响;
(2)实现OPT算法(最优置换算法)
、LRU算法(LeastRecently)
、FIFO算法(FirstINFirstOut)的模拟;
分页存储管理将一个进程的逻辑地址空间分成若干大小相等的片,称为页面或页。
在进程运行过程中,若其所要访问的页面不在内存而需把它们调入内存,但内存已无空闲空间时,为了保证该进程能正常运行,系统必须从内存中调出一页程序或数据,送磁盘的对换区中。
但应将哪个页面调出,须根据一定的算法来确定。
通常,把选择换出页面的算法称为页面置换算法(Page_ReplacementAlgorithms)。
一个好的页面置换算法,应具有较低的页面更换频率。
从理论上讲,应将那些以后不再会访问的页面换出,或将那些在较长时间内不会再访问的页面调出。
1、最佳置换算法OPT(Optimal)
它是由Belady于1966年提出的一种理论上的算法。
其所选择的被淘汰页面,将是以后永不使用的或许是在最长(未来)时间内不再被访问的页面。
采用最佳置换算法,通常可保证获得最低的缺页率。
但由于人目前还无法预知一个进程在内存