编辑模拟多进程共享临界资源.docx
《编辑模拟多进程共享临界资源.docx》由会员分享,可在线阅读,更多相关《编辑模拟多进程共享临界资源.docx(27页珍藏版)》请在冰豆网上搜索。
编辑模拟多进程共享临界资源
课程设计
课程设计名称:
操作系统原理
专业班级:
软件1301
学生姓名:
理金龙
学号:
201316920126
指导教师:
刘於勋
课程设计时间:
2015年7月6-11日
软件工程专业课程设计任务书
学生姓名
理金龙
专业班级
软件1301
学号
201316920126
题目
编程模拟多进程共享临界资源
课题性质
其它
课题来源
自拟课题
指导教师
刘於勋
同组姓名
主要内容
要求产生3个进程:
1、两个进程模拟需要进入临界区的用户进程,当需要进入临界区时,显示:
“进程x请求进入临界区…”,同时向管理进程提出申请;申请返回,表示进入了临界区。
在临界区中等待一段随机时间,并显示:
“进程x正在临界区…”;当时间结束,显示:
“进程x退出临界区…”,同时向管理进程提出退出申请;当申请返回,显示:
“进程x已退出临界区。
”
2、一个进程作为原语的管理进程,接受其他进程的临界区进入请求:
如果允许进入,则设置相应变量,然后返回;如果不允许进入,则进入循环等待,直到允许为止;
3、对临界区的访问应遵循空闲让进、忙则等待、有限等待、让权等待的准则。
4、进程间通信可以采用信号、消息传递、管道或网络通信方式。
任务要求
理解多进程共享临界资源的原理,并编程实现
参考文献
任满杰等《操作系统原理实用教程》电子工业出版社2006
汤子瀛《计算机操作系统》(修订版)西安电子科技大学出版社2001
张尧学史美林《计算机操作系统教程》实验指导清华大学出版社2000
罗宇等《操作系统课程设计》机械工业出版社2005
审查意见
指导教师签字:
教研室主任签字:
2015年7月6日
说明:
本表由指导教师填写,由教研室主任审核后下达给选题学生,装订在设计(论文)首页
信息科学与工程学院课程设计成绩评价表
课程名称:
操作系统原理
设计题目:
编程模拟多进程共享临界资源
专业:
软件工程班级:
软件1301姓名:
理金龙学号:
201316920126
序号
评审项目
分数
满分标准说明
1
内容
思路清晰,语言表达准确,概念清楚,论点正确;设计方法科学,分析归纳合理;结论严谨,设计有应用价值。
任务饱满,工作量适中
2
创新
内容新颖,设计能反映新技术,对前人工作有改进或突破,或有独特见解
3
完整性、实用性
整体构思后合理,理论依据充分,设计完整,实用性强
4
数据准确、可靠
数据准确,算法设计合理
5
规范性
设计格式、绘图、实验数据、标准的运用等符合有关标准和规定
6
纪律性
遵守课程设计纪律,听从指导教师安排,设计过程态度认真
7
答辩
准备充分,思路清晰、论点正确、对设计方案理解深入,问题回答有理有据,简明正确
总分
综
合
意
见
指导教师2015年7月12日
1需求分析
1、要求产生至少3个进程:
2、两个进程模拟需要进入临界区的用户进程,当需要进入临界区时,显示:
“进程x请求进入临界区…”,同时向管理进程提出申请;在临界区中等待一段随机时间,并显示:
“进程x正在临界区…”;当时间结束,显示:
“进程x退出临界区…”,同时向管理进程提出退出申请。
3、一个进程作为原语级管理进程,接受其他进程的临界区进入请求:
如果允许进入,则设置相应变量,然后返回;如果不允许进入,则进入循环等待,直到允许为止;
4、对临界区的访问应遵循空闲让进、忙则等待、有限等待、让权等待的准则。
5、进程间通信可以采用信号、消息传递、管道或网络通信方式。
2概要设计
2.1其中包含两个重要的数据结构:
2.11临界区:
Structcrform
{
Intsem;//临界区的信号量值sem
Inthead;//临界区等待队列的头,指向的是最先到的进程
Inttail;//临界区等待队列的尾,指向的是进入等待队列的进程
Intduilie[20];//存放的是等待的进程的信息,以便唤醒
待
}cr;
Cr.sem=1;//初始临界区信号量必须为一,因为只允许一个进程进入临界区
Cr.head=0;//初始时指向等待队列的第一个单元
Cr.tail=0;
2.12消息队列:
Structmsgform
{
Longmsgtype;//消息的类型,在取消息队列时用于区分哪些是该取的信息
Intmtext;//信息的内容,在这里是申请|退出进程的信息
};
2.2进程创建和控制:
fork()系统调用:
关键的语句:
intx,y;
while((x=fork())==-1);//创建子进程1
if(x==0)
{
//子进程1执行程序段
}
else
{
while((y=fork())==-1);
if(y==0)
{
//子进程2执行程序段
}
else
{
//父进程执行程序段
}
}
2.3设计流程图:
图1用户进程流程图
图管理进程
图3申请进入临界区处理子进程
图4申请退出处理子程序
3运行环境
3.1linux操作系统
3.2Gcc编译器
4开发工具和编程语言
4.1开发工具:
Gcc编译器
4.2编程语言:
C语言
5详细设计
子函数一:
voidinto()//申请进入临界区
{
structmsgformmsg;
key_thh=ftok("OSP.c",1);
intmsgqid=msgget(hh,0666|IPC_CREAT);
cr.sem--;//一旦申请进入临界区就得减1
msgrcv(msgqid,&msg,4,1,0);//接收消息--申请进入进程发送的类型为1
msg.msgtype=(long)msg.mtext;//并把接收到的消息内容作为回馈消息的消息类型
if(cr.sem>=0)//判断此时进程的状态,sem>=0可以获得临界区
{
if(msg.mtext==3)
printf("进程1:
进入临界区\n");
else
printf("进程2:
进入临界区\n");
msg.mtext=1;//现在允许进入,发送内容为1的消息给申请进程
msgsnd(msgqid,&msg,sizeof(int),0);
}
Else//到等待队列
{
if(msg.mtext==3)
printf("进程1:
进入等待队列\n");
else
printf("进程2:
进入等待队列\n");
cr.duilie[cr.tail]=msg.mtext;
cr.tail++;
if(cr.tail==20)
cr.tail=0;
msg.mtext=-1;
msgsnd(msgqid,&msg,sizeof(int),0);//若临界区忙,发送进入等待队列的消息给申请进入的进程
}
子函数二:
voidout()//申请退出临界区
{
structmsgformmsg;
key_thh=ftok("OSP.c",1);
intmsgqid=msgget(hh,0666|IPC_CREAT);
msgrcv(msgqid,&msg,4,2,0);//从消息队列上取下申请退出的消息
cr.sem++;
if(cr.tail!
=cr.head)//查看等待队列中是否有等待进入临界区的队列
{
//有则唤醒等待队列中等待的进程,并允许申请退出的进程退出
if(msg.mtext==3)
printf("进程1:
退出临界区\n");
else
printf("进程2:
退出临界区\n");
msg.msgtype=msg.mtext;
msg.mtext=0;
msgsnd(msgqid,&msg,sizeof(int),0);
intpid2=cr.duilie[cr.head];
cr.head++;
if(cr.head==20)
cr.head=0;
msg.mtext=1;
msg.msgtype=pid2;
if(pid2==3)
printf("进程1:
进入临界区\n");
else
printf("进程2:
进入临界区\n");
msgsnd(msgqid,&msg,sizeof(int),0);
}
else//如果等待队列上没有等待进入临界区的进程,直接向申请退出的进程发送消息,允许退出
{
if(msg.mtext==3)
printf("进程1:
退出临界区\n");
else
printf("进程2:
退出临界区\n");
msg.msgtype=msg.mtext;
msg.mtext=0;
msgsnd(msgqid,&msg,sizeof(int),0);
}
}
6调试分析
在作这个课题过程中遇到了主要的这样几个问题:
◆消息队列不能正常使用
错误原因1:
消息队列没有建立成功
解决办法:
在用消息队列之初先删除这个队列,然后再建立使用
错误原因2:
取到的结果总出现错误,没有统一的消息类型
解决办法:
定制统一的消息类型规则,依照规则使用消息类型
错误原因3:
进程需要的消息已经被取走,使得进程停留在取消息这一步不向下执行
解决办法:
是程序逻辑上的问题,仔细查看程序流程并操控好使得可以处于正常逻辑
◆申请到临界区退出临界区显示滞后(如有时会显示“进程一获得临界区”然后“进程二退出临界区”)
错误原因:
在管理进程中已经将临界区状态修改为空闲,却没有显示哪个进程退出临界区,这个退出的信息必须等到子进程上cpu时才会显示出来,而这中间有别的进程上cpu执行申请的操作,就会获得临界区,就会显示“进程获得临界区”,在此后退出临界区的进程才上cpu显示“退出临界区”。
解决办法:
将显示放到管理进程中,一旦有进程获得临界区或者退出临界区就做出显示。
7测试结果
测试数据:
1,0;1,2
测试截图:
图5开始界面
图6主程序运行界面
图7输入1,暂停运行
图8输入0,程序继续运行
图9输入2,程序退出运行
参考文献
[1]任满杰等《操作系统原理实用教程》电子工业出版社2006
[2]汤子瀛《计算机操作系统》(修订版)西安电子科技大学出版社2001
[3]张尧学史美林《计算机操作系统教程》实验指导清华大学出版社2000
[4]罗宇等《操作系统课程设计》机械工业出版社2005
[5]赛奎春、张雨编著,《VisualC++工程应用与项目实践》,海洋出版社,2005.1
心得体会
这次操作系统课设给了我很大的启发和提高。
一直以来自己我的编程基础不太好,常出现逻辑混乱,不注重细节问题,在这门课中我有了更深的理解;科学是不允许错误的,需要认真严谨的态度。
也正是因为如此我才有了进步。
理论联系实际,总会有更深刻的收获,通过这样的实际思考,动手修改操作,对理论有了深层次的理解,更加证实了理论,打消了心中不切实际的一些想法。
慢慢的会形成自己的一个实际经验,为日后的工作学习打下心里和知识上的基础。
小学期的课程真是紧张而又充实,确实是收获很多,心中也增加了几分自信,对未来的工作有更大的信息。
程序源代码(工程)
第一部分:
OSP.c
#include
#include
#include
#include
#include
#include
#include
#include"ran.h"
#defineMSGKEY898989
structcrform
{
intsem;
inthead;
inttail;
intduilie[20];
}cr;
structmsgform
{
longmsgtype;
intmtext;
};
voidinto();
voidout();
intmain(void){
puts("***********************提示信息***********************\n");
puts("在程序运行过程中:
\n");
puts("-------输入0继续运行程序\n");
puts("-------输入1暂停运行程序\n");
puts("-------输入2退出程序\n");
puts("*****************************************************\n");
intppid=getpid();
cr.sem=1;
cr.head=0;
cr.tail=0;
structShMe{
intnum;
intflags;
intp1;
intp2;
};
intshmid=shmget(IPC_PRIVATE,1024,0666|IPC_CREAT);
if(shmid==-1){
printf("共享内存区创建错误-----\n");
exit(0);
}
pid_tid=fork();
if(id<0){
printf("新进程创建错误!
!
2秒后自动退出。
。
。
。
。
\n");
sleep
(2);
exit(0);
}elseif(id==0){
pid_tid2=fork();
if(id2<0){
printf("新进程创建错误!
!
2秒后自动退出。
。
。
。
。
\n");
sleep
(2);
exit(0);
}elseif(id2==0){
structmsgformmsg;
key_thh=ftok("OSP.c",1);
intmsgqid=msgget(hh,0666|IPC_CREAT);
structShMe*addr;
addr=(structShMe*)shmat(shmid,0,0);
if(addr==(structShMe*)-1)
printf("映射内存错误1------\n");
intflags=0;
flags=addr->flags;
(*addr).p1=getpid();
while(flags==1||flags==0){
if(flags==0){
intq=10;
msg.mtext=3;
msg.msgtype=1;
printf("进程1:
申请进入临界区\n");
msgsnd(msgqid,&msg,sizeof(int),0);
kill(ppid,10);
while(q>0)
{
msgrcv(msgqid,&msg,sizeof(int),3,0);
intm=msg.mtext;
if(m==1)
{
printf("进程1:
进入共享内存区\n");
intny=addr->num;
intdg=rannum();
intuh=0;
for(uh=0;uhny++;
}
ny=ny%(99999-10000+1)+10000;
(*addr).num=ny;
msg.msgtype=2;
msg.mtext=3;
printf("进程1:
申请退出临界区\n");
msgsnd(msgqid,&msg,sizeof(int),0);
kill(ppid,12);
continue;
}
else
{
if(m==-1)
{
q--;
}
else
{
if(m==0)
{
intbb=rannum()%5;
sleep(bb);
flags=addr->flags;
break;
}
}
}
}
}else{
intbb=rannum()%5;
sleep(bb);
flags=addr->flags;
}
}
}else{
structmsgformmsg;
key_thh=ftok("OSP.c",1);
intmsgqid=msgget(hh,0666|IPC_CREAT);
structShMe*addr;
addr=(structShMe*)shmat(shmid,0,0);
if(addr==(structShMe*)-1)
printf("映射内存错误1------\n");
intflags=0;
flags=addr->flags;
(*addr).p2=getpid();
while(flags==1||flags==0){
if(flags==0){
intq=10;
msg.mtext=4;
msg.msgtype=1;
printf("进程2:
申请进入临界区\n");
msgsnd(msgqid,&msg,sizeof(int),0);
kill(ppid,10);
while(q>0)
{
msgrcv(msgqid,&msg,sizeof(int),4,0);
intm=msg.mtext;
if(m==1)
{
printf("进程2:
进入临界区\n");
intny=addr->num;
intdg=rannum();
intuh=0;
for(uh=0;uhny++;
}
ny=ny%(99999-10000+1)+10000;
(*addr).num=ny;
msg.msgtype=2;
msg.mtext=4;
printf("进程2:
申请退出临界区\n");
msgsnd(msgqid,&msg,sizeof(int),0);
kill(ppid,12);
continue;
}
else
{
if(m==-1)
{
q--;
}
else
{
if(m==0)
{
intbb=rannum()%5;
sleep(bb);
flags=addr->flags;
break;
}
}
}
}
}else{
intbb=rannum()%5;
sleep(bb);
flags=addr->flags;
}
}
}
}else{
key_thh=ftok("OSP.c",1);
intmsgqid=msgget(hh,0666|IPC_CREAT);
structShMe*addr;
addr=(structShMe*)shmat(shmid,0,0);
if(addr==(structShMe*)-1)
printf("映射内存错误3------\n");
(*addr).num=999;
(*addr).flags=0;
intflags=0;
signal(10,into);
signal(12,out);
scanf("%d",&flags);
while(flags==0||flags==1){
(*addr).flags=flags;
scanf("%d",&flags);
}
if(flags==2){
(*addr).flags=flags;
}
wait(addr->p1);
wait(addr->p2);
if(shmdt(addr)==-1)
printf("共享内存与控制进程断开错误........\n");
if(shmctl(shmid,IPC_RMID,NULL)==-1)
printf("shmctldeleteerror\n");
msgctl(msgqid,IPC_RMID,0);
printf("************》》》程序退出\n");
}
returnEXIT_SUCCESS;
}
voidinto()
{
structmsgformmsg;
key_thh=ftok("OSP.c",1);
intmsgqid=msgget(hh,0666|IPC_CREAT);
cr.sem--;
msgrcv(msgqid,&msg,4,1,0);
msg.msgtype=(long)msg.mtext;
if(cr.sem>=0)
{
if(msg.mtext==3)
printf("进程1:
进入临界区\n");
else
printf("进程2:
进入临界区\n");
msg.mtext=1;
msgsnd(msgqid,&msg,sizeof(int),0);
}
else
{
if(msg.mtext==3)
printf("进程1:
进入等待队列\n");
else
printf("进程2:
进入等待队列\n");
cr.duilie[cr.tail]=msg.mtext;
cr.tail++;
if(cr.tail==20)
cr.tail=0;
msg.mtext=-1;
msgsnd(msgqid,&msg,sizeof(int),0);
}
}
voidout()
{
structmsgformmsg;
key_thh=ftok("OSP.c",1);
intmsgqid=msgget(hh,0666|IPC_CREAT);
msgrcv(msgqid,&msg,4,2,0);
cr.sem++;
if(cr.tail!
=cr.head)
{
if(msg.mtext==3)
printf("进程1:
退出临界区\n");
else
printf("进程2:
退出临界区\n");
msg.msgtype=msg.mtext;
msg.mtext=0;
msgsnd(msgqi