生产者消费者 BoundedBuffer Problem.docx

上传人:b****8 文档编号:9368439 上传时间:2023-02-04 格式:DOCX 页数:16 大小:181.58KB
下载 相关 举报
生产者消费者 BoundedBuffer Problem.docx_第1页
第1页 / 共16页
生产者消费者 BoundedBuffer Problem.docx_第2页
第2页 / 共16页
生产者消费者 BoundedBuffer Problem.docx_第3页
第3页 / 共16页
生产者消费者 BoundedBuffer Problem.docx_第4页
第4页 / 共16页
生产者消费者 BoundedBuffer Problem.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

生产者消费者 BoundedBuffer Problem.docx

《生产者消费者 BoundedBuffer Problem.docx》由会员分享,可在线阅读,更多相关《生产者消费者 BoundedBuffer Problem.docx(16页珍藏版)》请在冰豆网上搜索。

生产者消费者 BoundedBuffer Problem.docx

生产者消费者BoundedBufferProblem

课程设计任务书

学生姓名:

专业班级:

软件0703

指导教师:

刘军工作单位:

计算机科学与技术学院

题目:

实现生产者消费者(Bounded-BufferProblem)问题

初始条件:

1.操作系统:

Linux

2.程序设计语言:

C语言

3.有界缓冲区内设有20个存储单元,其初值为0。

放入/取出的数据项按增序设定为1-20这20个整型数。

要求完成的主要任务:

(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)

1.技术要求:

1)为每个生产者/消费者产生一个线程,设计正确的同步算法

2)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的当前全部内容、当前指针位置和生产者/消费者线程的自定义标识符。

3)生产者和消费者各有两个以上。

4)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。

2.设计说明书内容要求:

1)设计题目与要求

2)总的设计思想及系统平台、语言、工具等。

3)数据结构与模块说明(功能与流程图)

4)运行结果与运行情况

(提示:

(1)有界缓冲区可用数组实现。

(2)编译命令可用:

     cc-lpthread-o 目标文件名  源文件名

(3)多线程编程方法参见附件。

3.调试报告:

1)调试记录

2)自我评析和总结

上机时间安排:

周一~五下午14:

00-18:

00(6月15日开始)

指导教师签名:

2010年6月15日

系主任(或责任教师)签名:

2010年6月15日

 

 

实现生产者消费者(Bounded–BufferProblem)问题

摘要

生产者与消费者问题是《操作系统》中经典进程同步问题的典型代表。

本设计介绍了基于单缓冲区和多缓冲区的生产者与消费者问题在C语言中的多种实现机制。

这种用C实现生产者与消费者问题的思想不仅可以更好的理解这方面的内容,而且还具有很强的实践意义。

1设计题目与要求

1.1设计题目:

实现生产者消费者(Bounded–BufferProblem)问题

1.2设计要求:

通过研究Linux的线程机制和信号量实现生产者消费者(BoundedBuffer)问题的并发控制。

2总的设计思想及系统平台、语言、工具

2.1设计思想:

2.1.1具体的要求

(1)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容.当前指针位置和生产者/消费者线程的标识符

(2)生产者和消费者各有两个以上

(3)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。

2.1.2POSIX无名信号量

PV操作是原子操作.也就是操作是不可以中断的,在一定的时间内,只能够有一个进程的代码在CPU上面执行.在系统当中,有时候为了顺利的使用和保护共享资源,提出了信号的概念.POSIX标准提出了有名信号量和无名信号量的概念,由于Linux只实现了无名信号量,我们在这里就只是介绍无名信号量了。

信号量的使用主要是用来保护共享资源,使的资源在一个时刻只有一个进程所拥有.为此可以使用一个信号灯.当信号灯的值为某个值的时候,就表明此时资源不可以使用.否则就表>示可以使用.为了提供效率,Linux系统提供了下面几个函数

POSIX的无名信号量的函数有以下几个:

intsem_init(sem_t*sem,intpshared,unsignedintvalue);

intsem_destroy(sem_t*sem);

intsem_wait(sem_t*sem);

intsem_trywait(sem_t*sem);

intsem_post(sem_t*sem);

intsem_getvalue(sem_t*sem);

sem_init创建一个信号灯,并初始化其值为value.pshared决定了信号量能否在几个进程间共享.由于目前Linux还没有实现进程间共享信号灯,所以这个值只能够取0.sem_destroy是用来删除信号灯的.sem_wait调用将阻塞进程,直到信号灯的值大于0.这个函数返回的时候自动的将信号灯的值的件一.sem_post和sem_wait相反,是将信号灯的内容加一同时发出信号唤醒等待的进程..sem_trywait和sem_wait相同,不过不阻塞的,当信号灯的值为0的时候返回EAGAIN,表示以后重试.sem_getvalue得到信号灯的值.

这几个函数的使用相当简单的.比如我们有一个程序要向一个系统请求一个资源时.首先创建一个信号灯,并使其初始值为1,表示有一个资源可用.然后一个进程调用sem_wait由于这个时候信号灯的值为1,所以这个函数返回,打印机开始打印了,同时信号灯的值为0了.如果第二个进程要使用,调用sem_wait时候,由于信号灯的值为0,资源不可用,于是被阻塞了.当第一个进程对资源的使用完毕以后,调用sem_post信号灯的值为1了,这个时候系统通知第二个进程,于是第二个进程的sem_wait返回.第二个进程开始工作了.

2.1.3SystemV信号量

为了解决上面的问题,也可以使用SystemV信号量.并且Linux实现了SystemV信号量.这样就可以用实例来解释了.SystemV信号量的函数主要有下面几个.

key_tftok(char*pathname,charproj);

intsemget(key_tkey,intnsems,intsemflg);

intsemctl(intsemid,intsemnum,intcmd,unionsemunarg);

intsemop(intsemid,structsembuf*spos,intnspos);

structsembuf{

shortsem_num;/*使用那一个信号*/

shortsem_op;/*进行什么操作*/

shortsem_flg;/*操作的标志*/

};

ftok函数是根据pathname和proj来创建一个关键字.semget创建一个信号量.成功时返回信号的ID,key是一个关键字,可以是用ftok创建的也可以是IPC_PRIVATE表明由系统选用一个关键字.nsems表明我们创建的信号个数.semflg是创建的权限标志,和创建一个文件的标志相同.

semctl对信号量进行一系列的控制.semid是要操作的信号标志,semnum是信号的个数,cmd是操作的命令.经常用的两个值是:

SETVAL(设置信号量的值)和IPC_RMID(删除信号灯).arg是一个给cmd的参数.

semop是对信号进行操作的函数.semid是信号标志,spos是一个操作数组表明要进行什么操作,nspos表明数组的个数.如果sem_op大于0,那么操作将sem_op加入到信号量的值中,并唤醒等待信号增加的进程.如果为0,当信号量的值是0的时候,函数返回,否则阻塞直到信号量的值为0.如果小于0,函数判断信号量的值加上这个负值.如果结果为0唤醒等待信号量为0的进程,如果小与0函数阻塞.如果大于0,那么从信号量里面减去这个值并返回.

2.1.4pthread_xxx()API

主要包含数据结构pthread_t它记录一个线程的号,主要包括下面几个函数,完成不同的功能:

intpthread_create(pthread_t*thread,pthread_attr_t*attr,void*(*start_routine)(void*),void*arg);创建一个线程。

pthread_join(pthread_t*thread,void**return);等待一个线程结束。

pthread_exit(void*returnval);结束一个线程。

2.2.系统平台:

一台Linux主机且有超级用户权限

2.3.编程工具:

VI编辑器,Gedit编辑器

3.模块说明

3.1.生产者进程:

if(fork()==0)

{

inti=0;

while(i<100)

{

semop(emptyid,&P,1);

semop(mutxid,&P,1);

array[*(set)%MAXSEM]=i+1;

printf("Producer%d\n",array[(*set)%MAXSEM]);

(*set)++;

semop(mutxid,&V,1);

semop(fullid,&V,1);

i++;

}//endofwhileinline62

sleep(10);

printf("Producerisover");

exit(0);

}/……

3.2消费者进程:

//消费者A进程

if(fork()==0)

{

while

(1)

{

semop(fullid,&P,1);

semop(mutxid,&P,1);

if(*get==100)

break;

*sum+=array[(*get)%MAXSEM];

printf("TheComsumerAGetNumber%d\n",array[(*get)%MAXSEM]);

(*get)++;

if(*get==100)

printf("Thesumis%d\n",*sum);

semop(mutxid,&V,1);

semop(emptyid,&V,1);

sleep

(1);

}//endofwhile

(1)inline82

printf("ConsumerAisover");

exit(0);

}//endofifinline81

else

{//消费者B进程

if(fork()==0)

{

while

(1)

{

semop(fullid,&P,1);

semop(mutxid,&P,1);

if(*get==100)

break;

*sum+=array[(*get)%MAXSEM];

printf("TheComsumerBGetNumber%d\n",array[(*get)%MAXSEM]);

(*get)++;

if(*get==100)

printf("Thesumis%d\n",*sum);

semop(mutxid,&V,1);

semop(emptyid,&V,1);

sleep

(1);

}//endofwhile

(1)inline105

printf("ConsumerBisover");

exit(0);

}//endofifinline103

}//endofelseinline101

}……

 

4.源程序:

#include

#include

#include

#include

#include

#include

#include

#include

#defineMAXSEM5

////声明三个信号灯ID

intfullid;

intemptyid;

intmutxid;

intmain()

{

structsembufP,V;;

unionsemunarg;

////声明共享内存

int*array;

int*sum;

int*set;

int*get;

//映射共享内存

array=(int*)mmap(NULL,sizeof(int)*5,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);

sum=(int*)mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);

get=(int*)mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);

set=(int*)mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);

*sum=0;

*get=0;

*set=0;

//生成信号灯

fullid=semget(IPC_PRIVATE,1,IPC_CREAT|00666);

emptyid=semget(IPC_PRIVATE,1,IPC_CREAT|00666);

mutxid=semget(IPC_PRIVATE,1,IPC_CREAT|00666);

//为信号灯赋值

arg.val=0;

if(semctl(fullid,0,SETVAL,arg)==-1)perror("semctlsetvalerror");

arg.val=MAXSEM;

if(semctl(emptyid,0,SETVAL,arg)==-1)perror("semctlsetvalerror");

arg.val=1;

if(semctl(mutxid,0,SETVAL,arg)==-1)perror("setctlsetvalerror");

//初始化P,V操作

V.sem_num=0;

V.sem_op=1;

V.sem_flg=SEM_UNDO;

P.sem_num=0;

P.sem_op=-1;

P.sem_flg=SEM_UNDO;

//生产者进程

if(fork()==0)

{

inti=0;

while(i<100)

{

semop(emptyid,&P,1);

semop(mutxid,&P,1);

array[*(set)%MAXSEM]=i+1;

printf("Producer%d\n",array[(*set)%MAXSEM]);

(*set)++;

semop(mutxid,&V,1);

semop(fullid,&V,1);

i++;

}//endofwhileinline62

sleep(10);

printf("Producerisover");

exit(0);

}//endofifinline59

else

{

//消费者A进程

if(fork()==0)

{

while

(1)

{

semop(fullid,&P,1);

semop(mutxid,&P,1);

if(*get==100)

break;

*sum+=array[(*get)%MAXSEM];

printf("TheComsumerAGetNumber%d\n",array[(*get)%MAXSEM]);

(*get)++;

if(*get==100)

printf("Thesumis%d\n",*sum);

semop(mutxid,&V,1);

semop(emptyid,&V,1);

sleep

(1);

}//endofwhile

(1)inline82

printf("ConsumerAisover");

exit(0);

}//endofifinline81

else

{//消费者B进程

if(fork()==0)

{

while

(1)

{

semop(fullid,&P,1);

semop(mutxid,&P,1);

if(*get==100)

break;

*sum+=array[(*get)%MAXSEM];

printf("TheComsumerBGetNumber%d\n",array[(*get)%MAXSEM]);

(*get)++;

if(*get==100)

printf("Thesumis%d\n",*sum);

semop(mutxid,&V,1);

semop(emptyid,&V,1);

sleep

(1);

}//endofwhile

(1)inline105

printf("ConsumerBisover");

exit(0);

}//endofifinline103

}//endofelseinline101

}//endofelseinline78

sleep(20);

return0;

}//endofmain

5.运行结果与运行情况

运行截图如下:

6.调试记录:

有三个worning:

7.自我评析和总结:

这次操作系统课程设计,我在设计过程中虽然遇到了困难,但是通过上网查阅资料很好的解决了问题,让我真正理解了Linux内核定时器的本质。

其实这个课程设计是我和同学一起完成的,虽然不是很完美,但是起码能让我们很好的理解了什么是生产者—消费者问题。

让我对互斥问题有了更深的见解。

8.参考文献

[1]《OperatingSystemConcepts(SixthEdition)(操作系统概念)影印版》AbrahamSilberschatz编高等教育出版社2003年

[2]《计算机操作系统教程(第三版)》张尧学编清华大学出版社2001年

[3]《操作系统原理(第三版)》庞丽萍华中科技大学出版社2000年

 

本科生课程设计成绩评定表

班级:

 软件0703  姓名:

   学号:

0120710680319

序号

评分项目

满分

实得分

1

学习态度认真、遵守纪律

10

2

设计分析合理性

10

3

设计方案正确性、可行性、创造性

20

4

设计结果正确性

40

5

设计报告的规范性

10

6

设计验收

10

总得分/等级

评语:

注:

最终成绩以五级分制记。

优(90-100分)、良(80-89分)、中(70-79分)、

及格(60-69分)、60分以下为不及格

 

                      指导教师签名:

                  2010年6月15日

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1