操作系统.docx
《操作系统.docx》由会员分享,可在线阅读,更多相关《操作系统.docx(17页珍藏版)》请在冰豆网上搜索。
操作系统
课程设计报告
课程名称:
操作系统课程设计
设计题目:
进程同步模拟—吃水果问题
系别:
软件学院
专业:
软件工程
学生姓名:
雷锹雷_______________________________________________________________________________________________________________________________学号:
20131736
指导教师:
李佳航
目录
1需求分析2
1.1吃水果问题的描述2
1.2问题的转换2
2功能设计3
2.1数据结构3
2.2模块说明3
2.3操作的流程图5
3开发平台及源程序的主要部分6
3.1开发平台6
3.2源程序7
4测试用例,运行结果与运行情况分析12
4.1测试用例12
4.2运行结果12
5自我评价与总结14
进程同步模拟设计
——吃水果问题
1需求分析
1.1吃水果问题的描述
•桌上有一只盘子,只能放得下一个水果。
•爸爸专向盘中放苹果,妈妈专向盘中放桔子,女儿专等吃盘中的苹果,儿子专等吃盘中的桔子。
用P、V操作写出它们能正确同步的程序。
1.2问题的转换
这是进程同步问题的模拟,可以把向盘子放或取水果的每一个过程可以转为一个进程的操作,这些进程是互斥的,同时也存在一定的同步关系。
通过编程实践时,实际是随机的调用人一个进程的操作,而这些进程的操作相当于程序中的函数调用。
而计算机在执行时每一个时刻只能执行一个操作,这就默认了互斥。
同步的模拟可以类似于函数调用时的前提关系即先决条件。
这样进程同步模拟就完全可以通过函数的调用来实现。
具体的每一个操作的对应的函数的关系:
爸爸向盘子中放一个苹果:
Father()
妈妈向盘子中放一个橘子:
Mother()
儿子从盘子取一个苹果:
Son()
女儿从盘子取一个橘子:
Daugther()
2功能设计
2.1数据结构
(1)用一个整型变量Plate_Size表示盘子,初始值为0,当放水果时Plate_Size加1,取水果时Plate_Size减1。
变量Plate_Size的最大值为1,当为1时表示盘子已经满,此时若进行放水果操作,放水果将处于等待状态;为0时表示盘子为空,此时若进行取水果操作,取水果操作将处于等待状态。
(2)整型变量orange和apple分别表示盘子中的橘子和苹果数目,初始都为0,Plate_Size=apple+orange。
(3)用四个bool型的变量Father_lag,Mother_lag,Son_lag,Daughter_lag,表示四个进程是否处于等待状态。
处于等待时,变量值为true。
(4)两个放水果进程进程同时处于等待状态时,若有取水果的操作将自动执行等待的放水果进程,执行按等待的先后顺序;一个取苹果或橘子进程同时候处于等待状态,若有放苹果或橘子的操作将自动执行等待的取进程,进行按等待的先后顺序。
(5)用一个随机的函数产生0—3的4个整数,分别对应六个进程的调用。
2.2模块说明
2.2.1主函数
用一个随机的函数产生0—3的4个整数,分别对应四个进程的调用,调用的次数可以自己输入,本程序共产生了10次随机的调用进程。
2.2.2进程p,v操作
•信号量初值S1=0,S2=0,S=1
•其中S为盘子的互斥信号量,S1为苹果信号量,S2为桔子信号量。
爸爸进程 妈妈进程 女儿进程 儿子进程
repeat repeat repeat repeat
P(s) P(s) P(s1) P(s2)
放苹果 放桔子 取苹果 取桔子
V(s1) V(s2) V(s) V(s)
untilfalse untilfalse untilfalse untilfalse
2.2.2四个进程函数
爸爸向盘子中放一个苹果操作:
Father()
妈妈向盘子中放一个橘子操作:
Mother()
儿子从盘子取一个橘子操作:
Son()
女儿从盘子取一个橘子操作:
Daugther()
2.2.3Print函数
用于输出盘子中苹果和橘子的个数,水果总个数及有哪些进程处于等待状态。
2.3操作的流程图
2.3.1放水果操作
爸爸放苹果进程的操作流程图:
2.3.2取水果操作
儿子取橘子的操作流程图:
3开发平台及源程序的主要部分
3.1开发平台
(1)使用系统:
windowxp
(2)使用语言:
c++
(3)开发工具:
c-free
3.2源程序
3.2.1各进程调用的函数
voidFather()//Father进程
{
apple++;
}
voidMother()//Mother进程
{
orange++;
}
voidSon()//Son进程
{
orange--;
}
voidDaughter()//Daughter进程
{
apple--;
}
3.2.2Print函数(打印盘子剩余水果及各进程等待状态)
voidPrint()//打印盘子剩余水果及各进程的等待状态的进程
{
cout<<"盘子中:
"<if(Father_lag==true)
cout<<"Father进程正在等待,";
if(Mother_lag==true)
cout<<"Mother进程正在等待,";
if(Son_lag==true)
cout<<"Son进程正在等待,";
if(Daughter_lag==true)
cout<<"Daughter进程正在等待,";
if(((Father_lag==false)&&(Mother_lag==false)&&(Son_lag==false)&&(Daughter_lag==false))!
=true)
cout<}
3.2.3主函数
intmain()
{
intk;
srand((unsigned)time(NULL));//srand()函数产生一个以当前时间开始的随机种子
for(k=0;k<10;k++)
{
inti;
cout<<"第"<"<i=rand()%6;//随进生成1-5.
Plate_Size=apple+orange;
switch(i)
{
case0:
cout<<"Father调用."<if(Plate_Size==1)
{
Father_lag=true;//Father()等待
Print();
if(Mother_lag==false)
MonFa_c=1;
}
else
{
Father();
Print();
if(Daughter_lag==true)
{
if(Daughter_b==1)
{
Daughter_lag=false;//Daughter等待取消
cout<<"处于等待的Daughter自动被调用"<Daughter();//处于等待的Daughter自动调用
Print();
Daughter_b=2;
}
else
{
if(Daughter_lag==true)
{
Daughter_lag=false;//Daughter等待取消
cout<<"处于等待的Daughter自动被调用"<Daughter();//处于等待的Daughter()自动调用
Print();
Daughter_b=0;
}
}
}
break;
case1:
cout<<"Mother调用."<if(Plate_Size==1)
{
Mother_lag=true;//等待
Print();
if(Father_lag==false)
MonFa_c=1;
}
else
{
Mother();
Print();
if(Son_lag==true)
{
if(Son_a==1)
{
Son_lag=false;//Son等待取消
cout<<"处于等待的Son自动被调用"<Son();//处于等待的Son()自动调用
Print();
Son_a=1;
}
}
else
{
if(Son_lag==true)
{
Son_lag=false;//Son等待取消
cout<<"处于等待的Son自动被调用"<Son();//处于等待的Son()自动调用
Print();
Son_a=0;
}
}
}
break;
case2:
cout<<"Son调用."<if(orange==0)
{
Son_lag=true;//Son处于等待
Print();
else
{
Son();
Print();
if((Father_lag==true)&&(Mother_lag==true))
{
if(MonFa_c==1)//Father和Mother同时处于等待,但Father先等待,因此先调用
{
Father_lag=false;
cout<<"处于等待的Father自动被调用"<Father();
Print();
MonFa_c=1;
}
else//Father和Mother同时处于等待,但Mother先等待,因此先调用
{
Mother_lag=false;
cout<<"处于等待的Mother自动被调用"<Mother();
Print();
MonFa_c=1;
}
}
else
{
if(Father_lag==true)//只有Father处于等待,调用
{
Father_lag=false;
cout<<"处于等待的Father自动被调用"<Father();
Print();
MonFa_c=0;
}
elseif(Mother_lag==true)//只有Mother处于等待,调用
{
Mother_lag=false;
cout<<"处于等待的Mother自动被调用"<Mother();
Print();
MonFa_c=0;
}
}
}
break;
case3:
cout<<"Daughter调用."<if(apple==0)
{
Daughter_lag=true;//Daughter等待
Print();
}
else
{
Daughter();
Print();
if((Father_lag==true)&&(Mother_lag==true))
{
if(MonFa_c==1)//Father和Mother同时处于等待,但Father先
{//等待,因此先调用
Father_lag=false;
cout<<"处于等待的Father自动被调用"<Father();
Print();
MonFa_c=2;
}
else//Father和Mother同时处于等待,但Mother先等待,因此先调用
{
Mother_lag=false;
cout<<"处于等待的Mother自动被调用"<Mother();
Print();
MonFa_c=1;
}
}
else
{
if(Father_lag==true)//只有Father处于等待,调用
{
Father_lag=false;
cout<<"处于等待的Father自动被调用"<Father();
Print();
MonFa_c=0;
}
elseif(Mother_lag==true)//只有Mother处于等待,调用
{
Mother_lag=false;
cout<<"处于等待的Mother自动被调用"<Mother();
Print();
MonFa_c=0;
}
}
}
break;
}
}
return0;
}
4测试用例,运行结果与运行情况分析
4.1测试用例
由于程序是模拟产生随机数的操作,执行相应的函数来模拟进程同步。
可以将程序运行两次将会得到不同的结果。
4.2运行结果
运行结果图:
5自我评价与总结
此次试验收获很大,即熟悉了基础调用知识,有提高了编程能力以及分析问题的能力。
使得我编程时可能出现的错误的认识,并如何去避免产生了新的认识。
对于此题我觉得除了可以用随机函数来产生随机数来调用相应的进程函数,以及思考进程的随机调用,进程之间的相互关系麻烦些,不过对进程同步了解的更加透彻了。