操作系统课程设计生产者消费者.docx
- 文档编号:26766290
- 上传时间:2023-06-22
- 格式:DOCX
- 页数:17
- 大小:236.45KB
操作系统课程设计生产者消费者.docx
《操作系统课程设计生产者消费者.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计生产者消费者.docx(17页珍藏版)》请在冰豆网上搜索。
操作系统课程设计生产者消费者
(操作系统课程设计)
生
产
者
和
消
费
者
学生姓名:
学生学号:
班级:
0311401、02、03、04班制
二〇一三年十二月
1、课程题目分析
这个题目是生产者向消费者提供商品,消费者消耗商品,并且两组人共用同一缓冲区。
生产者提供了商品之后消费者才能去取商品,消费者若不取走商品则当缓冲区用完之后生产者则不能再向缓冲区中添加新的商品。
思考问题:
(1)对于生产者进程:
每产生一个数据,则需去访问共用缓冲区是否有已满,未满则可以将该数据存入并通知消费者进程,否则不能。
(2)对于消费者进程:
每当想去消费(取出数据)时,则需访问缓冲区是否为空,为空则不能消费(取出数据),否则可以取,并通知生产者。
(3)缓冲区是个临界资源,所有的进程对于该空间都是共享的,所以,还有互斥问题存在。
2、课程设计目的
通过实验模拟生产者与消费者之间的关系,了解并掌握他们之间的关系及原理。
由此增加对进程同步问题的了解:
(1)掌握基本的同步互斥算法,理解生产者与消费者模型
(2)了解windows中多线程(多进程)的并发执行机制,线程(进程)间的同步于互斥
(3)学习使用windows中基本的同步对象,掌握相应的API。
3、课程设计内容
有n个生产者和m个消费者,连接在具有k个单位缓冲区的有界环转缓冲上,故又称有界缓冲问题。
其中Pi和Cj都是并发进程,只要缓冲区未满,生产者进程Pi所生产的产品就可投入缓冲区;类似地,只要缓冲区非空,消费者进程Cj就可以从缓冲区取走并消耗产品。
4、开发环境
操作系统:
Windows系统
编写语言:
C++语言
5、系统分析设计
(1)算法原理
生产者——消费者问题是典型的进程同步问题,这些进程必须按照一定的生产率和消费率来访问共享缓冲区,用P、V操作解决生产者和消费者共享单缓冲区的问题,可设置两个信号量empty和full,其初值分别为1和0,empty指示能否向缓冲区放入产品,full指示能否从缓冲区取出产品。
为了使其协调工作,必须使用一个信号量mutex(初值为1),以限制生产者和消费者互斥地对缓冲区进行存取,另用两个信号量empty1(初值为缓冲区大小)和full1(初值为0),以保证生产者不向已满的缓冲区中放入产品,消费者不从空缓冲区中取产品。
(2)功能描述
生产者功能描述:
在同一个进程地址空间内执行两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。
消费者功能描述:
消费者线程从缓冲区获得物品,然后释放缓冲区,当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。
(3)算法流程图
生产者流程图:
消费者流程图:
总的流程图:
(4)数据结构及部分函数描述
(1)类SeqSquare:
对类SeqSquare的声明及其中一些函数
classSeqSquare
{
public:
SeqSquare(intn);
~SeqSquare();
voidP(intx);//p操作
voidV(intx);//v操作
boolIsEmpty();//判断是否为空
boolIsFull();//判断是否已满
voiddeca();
voiddecb();
intgetSize();
intgetmaxSize();
intgettop();
intgeta();
intgetb();
protected:
private:
int*elements;
inttop,a,b,maxSize;
};
说明:
①用动态整型数组*elements来代表缓冲区,不管是生产产品还是对已有产品的消费都需要访问该缓冲区。
②函数IsFull()用于判断缓冲区是否已满,生产者能否使用缓冲区。
③函数IsEmpty()用于判断缓冲区是否为空,消费者能否使用缓冲区。
(2)生产者和消费者操作及显示函数showbuf:
voidproducer(SeqSquare*a)//生产者操作
{
a->P
(1);
}
voidconsumer(SeqSquare*a)//消费者操作
{
a->V
(1);
}
//缓冲区显示
voidshowbuf(SeqSquare*a)
{
inti=a->getSize();
}
(3)在实现本程序的生产者消费者模型时,具体地通过以下同步对象实现互斥:
①设一个互斥量Mutex,以实现生产者在查询和保留缓冲区的下一个空位置时进行互斥。
②每一个生产者用一个信号量与消费者同步,通过设置Full实现,该组信号量用于表示相应产品以生产。
同时用一个表示空缓冲区数目的信号量Empty进行类似的同步,指示缓冲区中是否存在空位置,以便开始生产下一个产品。
(4)调试过程
为解决生产者、消费者问题,应该设置两个资源信号量,其中一个表示空缓冲区的数目,用Full表示,其初值为用户输入的缓冲区的大小,另一个表示缓冲区中产品的数目,用Empty表示,其初值为0.另外,由于缓冲区是一个临界资源,必须互斥使用,所以还需要再设置一个互斥信号量Mutex,其初值为1.
在生产者、消费者问题中,信号量实现两种功能。
首先,他是生产产品和消费产品的计数器,计数器的初值是可使用的资源数目(缓冲区的长度)。
其次,他是确保产品的生产者和消费者之间的动作同步的同步器。
生产者要生产一个产品时,首先对资源信号量Full和互斥信号量Mutex进行P操作,申请资源。
如果可以通过的话,就生产一个产品,并把产品送人缓冲区。
然后对互斥信号量Mutex和资源信号量Empty进行V操作,释放资源。
消费者要消费一个产品时,首先对资源信号量Empty和互斥信号量Mutex进行P操作,申请资源。
如果可以通过的话就从缓冲区取出一个产品并消费掉。
然后对互斥信号量Mutex和资源信号量Full进行V操作,释放资源。
如果缓冲区中已经没有可用资源,就把申请资源的进程添加到等待队列的队尾。
如果有一个资源被释放,在等待队列中的第一个进程被唤醒并取得这个资源的使用权。
(5)参考资料
《操作系统教程》孙钟秀高等教育出版社
《C++程序设计》谭浩强高等教育出版社
6、运行实例及结果分析
(1)运行实例
缓冲区大小为3,先生产一件产品,显示缓冲区,再接着生产一件产品,消耗一件产品,显示缓冲区,在消耗两件产品,再生产4件产品,改变缓冲区的大小为6,显示缓冲区,选择一个未出现的选项,退出程序。
(2)结果显示
(3)结果分析
(1)在每个程序中需要先做P,后做V,二者要成对出现,夹在二者中间的代码段就是该进程的临界区。
(2)对同步信号量full和empty的P,V操作同样必须成对出现,但它们分别位于不同的程序中。
(3)无论在生产者进程中还是消费者进程中,两个P操作的次序不能颠倒:
应先执行同步信号量的P操作,然后执行互斥信号量的P操作。
否则可能造成进程死锁。
七、个人体验
虽然我也很想用java语言写这个程序,但是由于自己学艺不精,所以只能用C++写。
通过这个实验我发现我以前有很多知识都忘记了,重新拿起课本学习时发现原来很多不懂得问题都有了新的认识,有一种豁然开朗的感觉。
也为我考研开了一个好的开头。
我认为我完成的这个设计做的比较出色的地方是对C++语言中类以及数组的运用,其实这里我对数组的操作是按照“先进先出”的方法进行运作的,这是参考了栈的工作原理,因为缓冲区一般也是堆栈,比较符合设计要求。
这次实验中我感觉做的很粗糙,自己所想的模拟过程的确得到实现了,但是感觉灵活性不太高,思考还不过全面,应该以后多注意一下,多考虑考虑才是。
在这次实验中我重新将《C++程序设计》和《数据结构》的几个重要章节复习了一遍,对类、数组、C++的I/O流类库以及堆栈的语句格式、注意细节都再一次熟悉,感觉蛮有趣的。
不过,在编程过程中许多语句的小问题还真是出现不少,而且感觉自己对C++强大丰富的语句方法用得太呆板,不够灵活,总是想到那些常用的,而忽略了颗粒让语句更简短的方法,以后要多多注意才是。
8、附录
//生产者消费者1.cpp:
Definestheentrypointfortheconsoleapplication.
//
#include"stdafx.h"
#include"iostream"
usingnamespacestd;
classSeqSquare
{
public:
SeqSquare(intn);
~SeqSquare();
voidP(intx);//p操作
voidV(intx);//v操作
boolIsEmpty();//判断是否为空
boolIsFull();//判断是否已满
voiddeca();
voiddecb();
intgetSize();
intgetmaxSize();
intgettop();
intgeta();
intgetb();
protected:
private:
int*elements;
inttop,a,b,maxSize;
};
boolSeqSquare:
:
IsEmpty()//判断是否为空
{
return(top==-1)?
true:
false;
}
boolSeqSquare:
:
IsFull()//判断是否已满
{
return(top>=maxSize-1)?
true:
false;
}
voidSeqSquare:
:
deca()
{
a--;
}
voidSeqSquare:
:
decb()
{
b--;
}
intSeqSquare:
:
getSize()
{
returntop+1;
}
intSeqSquare:
:
getmaxSize()
{
returnmaxSize;
}
intSeqSquare:
:
gettop()
{
returntop;
}
intSeqSquare:
:
geta()
{
returna;
}
intSeqSquare:
:
getb()
{
returnb;
}
SeqSquare:
:
SeqSquare(intn)
{
top=-1;
a=b=0;
maxSize=n;
elements=newint[maxSize];
}
voidSeqSquare:
:
P(intx)
{
if(IsFull()==true)
{
a=a+1;
}
else
{
elements[++top]=x;
}
}
voidSeqSquare:
:
V(intx)
{
if(IsEmpty()==true)
{
b=b+1;
}
else
{
x=elements[top--];
}
}
voidproducer(SeqSquare*a)//生产者操作
{
a->P
(1);
}
voidconsumer(SeqSquare*a)//消费者操作
{
a->V
(1);
}
SeqSquare:
:
~SeqSquare()
{
deleteelements;
}
//缓冲区显示
voidshowbuf(SeqSquare*a)
{
inti=a->getSize();
}
intmain()
{
inti,n;
cout<<"请输入缓冲区大小:
"< cin>>n; SeqSquare*s; s=newSeqSquare(n); while(i! =4) { cout<<"请选择操作: "< cout<<"1.生产一件产品;2.消费一件产品"< cout<<"3.显示缓冲区;4.退出系统。 "< cout<<"5.需要改变缓冲区大小! "< cin>>i; switch(i) { case1: producer(s); if(s->geta()==0) { cout< "< } else { cout< "< s->deca(); } break; case2: consumer(s); if(s->getb()==0) { cout< "< } else { cout< "< } break; case3: showbuf(s); cout< "< "<<(n-s->getSize())< break; case4: cout< "< break; case5: cout< "< cin>>n; s=newSeqSquare(n); cout< "< break; default: cout< "< } } return0; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 操作系统 课程设计 生产者 消费者