搜档网
当前位置:搜档网 › 编辑模拟多进程共享临界资源

编辑模拟多进程共享临界资源

编辑模拟多进程共享临界资源
编辑模拟多进程共享临界资源

课程设计

课程设计名称:操作系统原理

专业班级:软件1301

学生姓名:理金龙

学号: 201316920126

指导教师:刘於勋

课程设计时间: 2015年7月6-11日

软件工程专业课程设计任务书

说明:本表由指导教师填写,由教研室主任审核后下达给选题学生,装订在设计(论文)首页

信息科学与工程学院课程设计成绩评价表

课程名称:操作系统原理

设计题目:编程模拟多进程共享临界资源

1 需求分析

1、要求产生至少3个进程:

2、两个进程模拟需要进入临界区的用户进程,当需要进入临界区时,显示:“进程x请求进入临界区…”,同时向管理进程提出申请;在临界区中等待一段随机时间,并显示:“进程x正在临界区…”;当时间结束,显示:“进程x退出临界区…”,同时向管理进程提出退出申请。

3、一个进程作为原语级管理进程,接受其他进程的临界区进入请求:如果允许进入,则设置相应变量,然后返回;如果不允许进入,则进入循环等待,直到允许为止;

4、对临界区的访问应遵循空闲让进、忙则等待、有限等待、让权等待的准则。

5、进程间通信可以采用信号、消息传递、管道或网络通信方式。

2 概要设计

2.1 其中包含两个重要的数据结构:

2.11 临界区:

Struct crform

{

Int sem; //临界区的信号量值sem

Int head; //临界区等待队列的头,指向的是最先到的进程

Int tail; //临界区等待队列的尾,指向的是进入等待队列的进程

Int duilie[20]; //存放的是等待的进程的信息,以便唤醒

}cr;

Cr.sem=1; //初始临界区信号量必须为一,因为只允许一个进程进入临界区

Cr.head=0; //初始时指向等待队列的第一个单元

Cr.tail=0;

2.12 消息队列:

Struct msgform

{

Long msgtype; //消息的类型,在取消息队列时用于区分哪些是该取的信息

Int mtext; //信息的内容,在这里是申请|退出进程的信息

};

2.2 进程创建和控制:fork()系统调用:

关键的语句:

int x,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.1 linux操作系统

3.2 Gcc编译器

4 开发工具和编程语言

4.1 开发工具:

Gcc编译器

4.2 编程语言:

C语言

5 详细设计

子函数一:

void into() //申请进入临界区

{

struct msgform msg;

key_t hh=ftok("OSP.c",1);

int msgqid=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); //若临界区忙,发送进入等待队列的消息给申请进入的进程

}

子函数二:

void out() //申请退出临界区

{

struct msgform msg;

key_t hh=ftok("OSP.c",1);

int msgqid=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);

int pid2=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] 赛奎春、张雨编著,《Visual C++ 工程应用与项目实践》,海洋出版社,2005.1

心得体会

这次操作系统课设给了我很大的启发和提高。一直以来自己我的编程基础不太好,常出现逻辑混乱,不注重细节问题,在这门课中我有了更深的理解;科学是不允许错误的,需要认真严谨的态度。也正是因为如此我才有了进步。理论联系实际,总会有更深刻的收获,通过这样的实际思考,动手修改操作,对理论有了深层次的理解,更加证实了理论,打消了心中不切实际的一些想法。慢慢的会形成自己的一个实际经验,为日后的工作学习打下心里和知识上的基础。小学期的课程真是紧张而又充实,确实是收获很多,心中也增加了几分自信,对未来的工作有更大的信息。

程序源代码(工程)第一部分:OSP.c #include

#include

#include

#include

#include #include

#include

#include "ran.h"

#define MSGKEY 898989

struct crform

{

int sem;

int head;

int tail;

int duilie[20];

}cr;

struct msgform

{

long msgtype;

int mtext;

};

void into();

void out();

int main(void) {

puts("***********************提示信息***********************\n");

puts("在程序运行过程中:\n");

puts("-------输入 0 继续运行程序\n");

puts("-------输入 1 暂停运行程序\n");

puts("-------输入 2 退出程序\n");

puts("*****************************************************\n");

int ppid=getpid();

cr.sem = 1;

cr.head=0;

cr.tail=0;

struct ShMe{

int num;

int flags;

int p1;

int p2;

};

int shmid=shmget(IPC_PRIVATE,1024,0666|IPC_CREAT);

if(shmid==-1){

printf("共享内存区创建错误-----\n");

exit(0);

}

pid_t id = fork();

if (id<0) {

printf("新进程创建错误!! 2秒后自动退出。。。。。\n");

sleep(2);

exit(0);

}else if (id==0) {

pid_t id2 = fork();

if(id2<0){

printf("新进程创建错误!! 2秒后自动退出。。。。。\n");

sleep(2);

exit(0);

}else if (id2==0) {

struct msgform msg;

key_t hh=ftok("OSP.c",1);

int msgqid=msgget(hh,0666|IPC_CREAT);

struct ShMe * addr;

addr=(struct ShMe*)shmat(shmid,0,0);

if(addr==(struct ShMe*)-1)

printf("映射内存错误1------\n");

int flags=0;

flags=addr->flags;

(*addr).p1=getpid();

while(flags==1||flags==0){

if(flags==0){

int q=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);

int m=msg.mtext;

if(m==1)

{

printf("进程1: 进入共享内存区\n");

int ny=addr->num;

int dg=rannum();

int uh=0;

for(uh=0;uh

ny++;

} 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)

{

int bb=rannum()%5;

sleep(bb);

flags=addr->flags;

break;

}

}

}

}

}else{

相关主题