欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > DOC文档下载  

    多线程实现生产者消费者.doc

    • 资源ID:4281717       资源大小:573KB        全文页数:14页
    • 资源格式: DOC        下载积分:16金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要16金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    多线程实现生产者消费者.doc

    嵌入式Linux编程课程设计题目:多线程实现生产者消费者之间的通信班 级: 计算机应用xxxx班 学 号: 12号 姓 名: xx 指导教师: xxx 日 期: 2014.6.232014.6.27 目 录一、课程设计说明1二、概要设计1三、模块设计2四、详细设计4五、程序调试6六、总结8七、参考文献9八、附录10一、课程设计说明生产者-消费者(producer-consumer)问题,也称作有界缓冲区(bounded-buffer)问题,两个进程共享一个公共的固定大小的缓冲区。其中一个是生产者,用于将消息放入缓冲区;另外一个是消费者,用于从缓冲区中取出消息。问题出现在当缓冲区已经满了,而此时生产者还想向其中放入一个新的数据项的情形,其解决方法是让生产者此时进行休眠,等待消费者从缓冲区中取走了一个或者多个数据后再去唤醒它。同样地,当缓冲区已经空了,而消费者还想去取消息,此时也可以让消费者进行休眠,等待生产者放入一个或者多个数据时再唤醒它。本次课设通过研究Linux的进程机制和信号量实现生产者消费者问题的并发控制。二、概要设计本作业是完善课件上的线程综合实例的练习生产者-消费者问题,重构这个程序的框架,完成性能分析,使之进一步理解掌握Linux下线程的同步、通信以及互斥和多线程的安全问题。一般情况下,解决互斥方法常用信号量和互斥锁,即semaphore和mutex,而解决这个问题,多采用一个类似资源槽的结构,每个槽位标示了指向资源的指针以及该槽位的状态,生产者和消费者互斥查询资源槽,判断是否有产品或者有空位可以生产,然后根据指针进行相应的操作。同时,为了告诉生产者或者消费者资源槽的情况,还要有一个消息传送机制,无论是管道还是线程通信。然而,本次试验有几个特殊的要求:1、循环缓冲。2、除了stderr,stdout等外,只用小于2个的互斥锁、3、放弃资源槽分配机制,采用额外的数据结构。4、生产者一直持续生产,形成生产消费的良性循环。首先,使用一个互斥锁,意味着资源槽机制就不能使用了。因为资源槽虽以用一个互斥锁完成,但是需要有额外的通信,如果使用管道通信,则管道也必须是互斥,这就不满足1个互斥锁的要求。其次,要求生产者一直生产,这就否定了另外一种方法:消费者、生产者的位置均平等,消费者消费的时候生产者不能生产,生产者生产的时候消费者不能消费。因此,就需要采用A要求,也就是循环链表的形式。为了保证互斥要求,需要定义一个数据结构,这个数据结构包含两个指针,一个读一个写,同时有一个资源数目量,告诉生产者和消费者是否可以生产或者消费。由于该数据结构很小,因而可以对此结构互斥访问。同时,对于每组数据,都有一个标志位,表示此组数据是否被占用,生产者和消费者均可以先占用此位置然后完成相应的操作。当消费者互斥访问此结构时,首先判断是否有数据可以取,如果没有,直接等待,若有数据可取,先更改标志位占用此数据,并将资源数目-1。然后交出互斥,把数据拷贝到自己缓冲区内,清空数据。当生产者访问时,首先判断有没有空位可以生产,如果没有,直接等待,若有数据可以生产,先判断该位是否被占用,如果没被占用,则占用此位置进行生产。生产完成后,将占用位改为未占用,同时将资源数目+1。三、模块设计采用信号量来解决n个进程的临界区问题,这n个进程共享一个信号量mutex(mutual exclusion),并初始化为1。利用p ,v原语操作结合信号量实现生产者和消费者进程对缓冲区的互斥访问。3.1 生产者进程 if(fork() = 0 ) int i = 0; while( i < 100) semop(emptyid , &P ,1 );semop(mutxid , &P , 1);array*(set)%MAXSEM = i + 1; printf("Producer %dn", array(*set)%MAXSEM); (*set)+; semop(mutxid , &V , 1); semop(fullid , &V , 1); i+; /end of while in line 62 sleep(10); printf("Producer is over"); exit(0);图 3-1 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("The ComsumerA Get Number %dn", array(*get)%MAXSEM ); (*get)+; if( *get =100) printf("The sum is %d n ", *sum); semop(mutxid , &V , 1); semop(emptyid , &V ,1 );图 3-2 sleep(1); /end of while(1) in line 82 printf("ConsumerA is over"); exit(0);/end of if in line 81else /消费者B进程 if(fork()=0) while(1) semop(fullid , &P , 1); semop(mutxid , &P , 1); if(*get = 100) break; *sum += array(*get)%MAXSEM; printf("The ComsumerB Get Number %dn", array(*get)%MAXSEM ); (*get)+; if( *get =100) printf("The sum is %d n ", *sum); semop(mutxid , &V , 1); semop(emptyid , &V ,1 ); sleep(1); /end of while(1) in line105 printf("ConsumerB is over"); exit(0); /end of if in line 103 /end of else in line 101 四、详细设计一、 主函数图 4-1二、统计线程图 4-2三、生产者线程图 4-3四、消费者线程图 4-4五、程序调试5.1 调试记录有三个warning:图 5-1-1图 5-1-2图 5-1-35.2 运行结果图 5-2-1图5-2-2六、总结在这次的课程设计中,我遇到了很大的困难,对一些概念很不理解,不过通过和同学交流又上网查阅资料很好的解决了问题,让我在这个过程中学到很多东西,也进一步理解操作系统的概念,同时对Linux编程也有了更多的学习。这个课程设计并不是很完美,但是起码能让我们很好的理解了什么是生产者消费者问题。让我对互斥问题有了更深的见解,同时也认识的到自己很大的不足,在以后的学习中会加以克服,增强自己的问题分析能力和动手实践能力。虽然实验以前我已经对信号量机制解决进程间同步问题的原理有了很清楚的认识,但是此次课程设计中仍然遇到了很多问题,如Linux系统下各种系统调用以及函数的各种参数,都花费了我很多时间去网上看各种资料虽然Linux系统中可以很方便的阅读源代码以及使用man命令进行相应指令的查看,但是全英文的资料让人看了不免有些发怵,看来还要多多加强计算机专业英语的学习,以后便可以在Linux系统中查看各种帮助文件。另一个问题就是在编译的时候遇到的,刚开始用gcc o main main.c 进行编译的时候总是提示出错,后来查了相关资料才知道pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a,所以在使用pthread_create()等函数时,需要链接该库才能编译通过。以前再用Windows IDE进行编程的时候基本上不会遇到这样的问题,看来的确IDE为我们做了很多工作,隐藏了一些技术细节,有时候隐藏这些细节虽然可以方便我们,却让我们离真相越来越远。最近使用Linux进行相关的编程操作,感悟还是挺多的。Windows下的层层封装的确让我们感到很方便,但同时也让我们编程变得越来越不灵活。因为我们不用再去了解底层的东西因此一遇到问题就会束手无策。这段时间一直用Linux进行编程,感觉很方便,跟我以前想象地完全不一样,而且我掌握了不少命令,比我以前用鼠标操作的时候快多了,而且在Bash下可以用Ctrl+Z随时中止正在运行的进程或命令,再用fg %id 重新运行。Linux下的编程也很方便,我还了解了Makefile的编写方法,在多文件编程的时候可以极高地提高效率。 总之,我之后会加强专业英语的学习,以便更好的利用Linux操作系统进行编程之路的学习。七、参考文献1Operating System Concepts(Sixth Edition)(操作系统概念)影印版 Abraham Silberschatz编 高等教育出版社 2003年2 操作系统 罗宇 邹鹏 吴刚 等编著 电子工业出版社 2006年2计算机操作系统教程(第三版) 张尧学编 清华大学出版社 2001年3 计算机操作系统 第三版 汤晓丹 梁红兵 哲凤屛 汤子瀛 编著西安电子科技大学出版社 2009年4 操作系统原理(第三版) 庞丽萍 华中科技大学出版社2000年八、附录#include <sys/mman.h>#include <sys/types.h>#include <linux/sem.h>#include <fcntl.h>#include <unistd.h>#include <stdio.h>#include <errno.h>#include <time.h>#define MAXSEM 5/声明三个信号灯IDint fullid;int emptyid;int mutxid;int main() struct sembuf P,V; union semun arg; /声明共享内存 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, zeof( int ),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0); get=(int*)mmap(NULL,sizeof( int ),PROT_READ|PROT_WRITE,MAP_SHAR ED|MAP_ANONYMOUS,-1,0); set=(int*)mmap(NULL,sizeof( int ),PROT_READ|PROT_WRITE,MAP_SHAR ED|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("semctl setval error"); arg.val = MAXSEM; if(semctl(emptyid , 0 ,SETVAL , arg) = -1)perror("semctl setval error"); arg.val = 1; if(semctl(mutxid , 0 ,SETVAL , arg) = -1) perror("setctl setval error"); /初始化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 ) int i = 0; while( i < 100) semop( id , &P ,1 ); semop(mutxid , &P , 1); array*(set)%MAXSEM = i + 1; printf("Producer %dn", array(*set)%MAXSEM); (*set)+; semop(mutxid , &V , 1); semop(fullid , &V , 1); i+; sleep(10); printf("Producer is over"); exit(0); else /消费者A进程 if(fork()=0) while(1) semop(fullid , &P , 1); semop(mutxid , &P , 1); if(*get = 100) break; *sum += array(*get)%MAXSEM; printf("The ComsumerA Get Number %dn", array(*get)%MAXSEM ); (*get)+; if( *get =100) printf("The sum is %d n ", *sum); semop(mutxid , &V , 1); semop(emptyid , &V ,1 ); sleep(1); printf("ConsumerA is over"); exit(0);else /消费者B进程 if(fork()=0) while(1) semop(fullid , &P , 1); semop(mutxid , &P , 1); if(*get = 100) break; *sum += array(*get)%MAXSEM; printf("The ComsumerB Get Number %dn", array(*get)%MAXSEM ); (*get)+; if( *get =100) printf("The sum is %d n ", *sum); semop(mutxid , &V , 1); semop(emptyid , &V ,1 ); sleep(1); printf("ConsumerB is over"); exit(0); sleep(20); return 0;

    注意事项

    本文(多线程实现生产者消费者.doc)为本站会员(牧羊曲112)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开