已阅读5页,还剩12页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
武汉理工大学华夏学院操作系统原理课程设计说明书操作系统设计报告 姓名:韦李 学号:5 日期:2013年12月30日 目录第1章 需求分析11.1 设计题目11.2 设计目的11.3 设计环境与工具11.3.1 设计环境11.3.2 设计工具11.4 设计要求1第2章 概要设计22.1 设计内容与原理22.1.1 设计内容22.1.2 设计原理22.2 程序流程图3第3章 详细设计53.1 数据结构53.2 算法说明53.2.1 同步机制原语算法53.2.2 具体算法实现63.3 具体程序实现73.3.1 生产者方法73.3.2 消费者方法73.3.3 多线程实现8第4章 程序运行结果和分析104.1 运行结果104.2 结果分析10第5章 总结与体会11附录:源程序14第1章 需求分析1.1 设计题目用多线程同步方法解决生产者消费者问题1.2 设计目的1.通过编程实现生产者与消费者问题,了解进程同步的概念,理解信号量机制的原理。2.掌握运用信号量解决进程同步问题的方法,学会运用进程的同步于互斥结局生产者与消费者的冲突问题。3.通过研究Linux的线程机制和信号量实现生产者消费者问题的并发控制。1.3 设计环境与工具1.3.1 设计环境Fedora 10操作系统1.3.2 设计工具 Vi 编辑器,gcc编译器1.4 设计要求 1.有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1-20这20个整型数。2.每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容、当前指针位置和生产者/消费者线程的标识符。3.生产者和消费者各有两个以上。4.多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。第2章 概要设计2.1 设计内容与原理2.1.1 设计内容在同一个进程地址空间内执行的两个线程,生产者生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区,当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区,当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,知道新的物品被生产出来,我的具体做法也是如此,建立缓冲区,生产者生产的产品放入,消费者从中取产品,如果没有产品,则等待。2.1.2 设计原理 要实现生产者与消费者的互斥关系,生产者和消费者进程之间必须满足两个同步条件: 1.只有在缓冲池中至少有一个缓冲区已存入消息后,消费者才可以从中提取消息,否则消费者必须等待。 2.只有缓冲池中至少有一个缓冲区是空时,生产者才可以把消息放入缓冲区中,否则生产者必须等待。要满足第一个同步条件,设置一个同步信号量full_sem,它的值为20时整个缓冲区满,这个资源是消费者进程所拥有,消费者进程可以申请资源,对它做P操作;另外一个信号量empty_sem,它的初值为20,表示整个缓冲区都是空的。可以用full_sem表示空缓冲区数量,empty_sem表示满缓冲区数量,另外有界缓冲区是一个临界资源,必须互斥使用,所以必须再设置一个互斥信号量mux,初值为1。在生产者/消费者问题中,信号量实现两种功能,首先,它是跟踪资源的生产和消费的计数器,其次,它是协调产品的生产者和消费者之间动作同步的同步器。消费者通过再一指派给它的信号量上做P操作来表示消耗资源,而生产者通过再同一个信号量上做V操作来表示生产资源。而这种信号量的实施中,计数在每次P操作后减1,而在每次V操作后加1。这个计数器的初始值是可利用的资源数目,当资源是不可利用时,将申请资源的进程防止在等待队列中,如果有一个资源释放,在等待队列中的第一个进程被唤醒并得到资源的控制权。假定在生产者和消费者之间的公用缓冲区中,具有n个缓冲区,这时可以利用互斥信号量mutex实现诸进程对缓冲区的互斥使用,利用信号量empty和full分别表示缓冲池中空缓冲区和满缓冲区的数量,又假定这些生产者和消费者互相等效果,只要缓冲区未满,生产者便可以将消息送入缓冲池,只要缓冲池未空,消费者便可以从缓冲池中取走一个消息。2.2 程序流程图生产一条数据是否可用存储单元是否可用存入一条数据归还使用权数据单元加1,唤醒一个消费者等待资源,阻塞被唤醒等待使用权,阻塞被唤醒无有否图 2.1 生产者流程图是否有数据单元是否可用取走一条数据归还使用权空单元加1,唤醒一个生产者消费数据等待资源,阻塞被唤醒等待使用权,阻塞被唤醒有是否图2.2 消费者流程图第3章 详细设计3.1 数据结构#define N 2 / 消费者或者生产者的数目#define M 10 / 缓冲数目int in = 0; / 生产者放置产品的位置int out = 0; / 消费者取产品的位置int buffM = 0; / 缓冲初始化为0, 开始时没有产品sem_t empty_sem; / 同步信号量, 当满了时阻止生产者放产品sem_t full_sem; / 同步信号量, 当没产品时阻止消费者消费pthread_mutex_t mutex; / 互斥信号量, 一次只有一个线程访问缓冲int product_id = 0; /生产者idint prochase_id = 0; /消费者id3.2 算法说明3.2.1 同步机制原语算法P进程不能往“满”的缓冲区中放产品,设置信号量为sem_empty;Q进程不能从“空”的缓冲区中取产品,设置信号量为sem_full。先设置信号量:sem_empty初值为1,sem_full初值为0实现原语如下:P: Q:While(true) while(true) 生产一个产品; P(sem_full); P(Sem_empty); 从缓冲区去产品 送产品到缓冲区; V(sem_empty); V(sem_full); 消费产品; P原语操作的主要动作是:1.sem减1;2.若sem减1后仍大于或等于零,则进程继续执行;3.若sem减1后仍小于零,则该进程被阻塞后与该信号所对应的队列中,然后转入进程调度;V原语操作的主要动作时:1Sem加1;2.若相加结果大于零;3.若相加结果小于或者等于零,则从该信号的等待队列中唤醒一等待队列,然后再返回原进程继续执行或转入进程调度。3.2.2 具体算法实现Semaphore mutex=1;/定义互斥信号量Semaphore empty=n;/定义同步信号量Semaphore full=0;itemn;/定义缓冲池Int in=0;/生产者放置位置Int out=0;/消费者放置位置Producer() /生产者 While(true) Produce an item in next_product;/ 生产者产生数据 Swait(empty,mutex);/等待缓冲区空信号量 Arrayin=next_product;/将数据放入缓冲池 In=(in+1)%n; Ssignal(mutex,full); Consumer() /消费者 While(true) Swait(full,mutex);/等待缓冲池满信号量 Next_consumer=arrayout;/从缓冲池取出数据 Out=(out+1)%n; Ssignal(mutex,empty); Consume the product in next_consumer;/等待下一个消费者取出数据 3.3 具体程序实现3.3.1 生产者方法在生产者方法的实现中,先产生一个数据,然后判断缓冲池空信号量,如果缓冲池至少有一个为空则将先将缓冲池上锁,然后将数据放入缓冲池,将放入数据位置指针后移,放入数据后将缓冲池解锁;如果缓冲池为满,则生产者线程进入阻塞状态,进入进程调度队列,并等待缓冲池空信号量。/* 生产者方法 */ void *product()int id = +product_id;while(1) / 用sleep的数量可以调节生产和消费的速度,便于观察 sleep(1); /sleep(1); sem_wait(&empty_sem);/等待缓冲池空信号量 pthread_mutex_lock(&mutex);/对缓冲池上锁 in = in % M; printf(product%d in %d. like: t, id, in);/显示生产者ID buffin = 1; /将数据放入缓冲区 print(); /打印存数结果 +in; /写入位置指针后移 pthread_mutex_unlock(&mutex);/对缓冲池解锁 sem_post(&full_sem); /等待缓冲池满信号量3.3.2 消费者方法在消费者方法实现中,首先判断缓冲池满信号量,如果缓冲池中不为空,则进行取数操作,并对缓冲池上锁,取数后,显示消费者ID,随后对缓冲池解锁;如果缓冲池为空,则不对缓冲池操作,消费者线程进入阻塞状态,进入线程调度队列。/* 消费者方法 */void *prochase()int id = +prochase_id;while(1) / 用sleep的数量可以调节生产和消费的速度,便于观察 sleep(1);/sleep(1); sem_wait(&full_sem);/等待缓冲池满指针 pthread_mutex_lock(&mutex);/对缓冲池上锁 out = out % M; printf(prochase%d in %d. like: t, id, out);/答应消费者ID buffout = 0; print();/答应信息 +out;/取数指针后移 pthread_mutex_unlock(&mutex);/对缓冲池解锁 sem_post(&empty_sem); 3.3.3 多线程实现在线程的创建时,可以用函数pthread_create用来创建一个线程,它的原型为:int pthread_create _P (pthread_t *_thread, _const pthread_attr_t *_attr,void *(*_start_routine) (void *), void *_arg);第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数。这里,我们的函数thread不需要参数,所以最后一个参数设为空指针。第二个参数我们也设为空指针,这样将生成默认属性的线程函数pthread_join用来等待一个线程的结束。函数原型为:extern int pthread_join _P (pthread_t_th,void*_thread_return);第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。一个线程的结束有两种途径,一种是象我们上面的例子一样,函数结束了,调用它的线程也就结束了;另一种方式是通过函数pthread_exit来实现。它的函数原型为:extern void pthread_exit _P (void *_retval) _attribute_ (_noreturn_);唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给thread_return。最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。/ 创建N个生产者线程for(i = 0; i N; i+) reti = pthread_create(&id1i, NULL, product, (void *)(&i);/将生产者方法创建成线程 if(reti != 0) printf(product%d creation failed n, i);/打印线程创建信息 exit(1); /创建N个消费者线程for(i = 0; i N; i+) reti = pthread_create(&id2i, NULL, prochase, NULL);/将消费者方法创建成线程 if(reti != 0) printf(prochase%d creation failed n, i);/打印消费者线程创建信息 exit(1); /销毁线程for(i = 0; i N; i+) pthread_join(id1i,NULL); pthread_join(id2i,NULL);exit(0); 第4章 程序运行结果和分析4.1 运行结果4.2 结果分析从运行结果截图中可以看到:程序创建了5个生产者线程,4个消费者线程。每次生产者线程产生一个数据并存入缓冲池中,每次消费者线程从缓冲池中取出一个数,并且在每次生产者线程产生数据和消费者取出数据后都打印缓冲区中的数据。第5章 总结与体会经过快一个星期的努力,终于完成了这个课程设计,从刚开始看到这个课程设计题目时的毫无头绪到最后实现算法和完成课程设计报告,遇到了很多的困难。在平时操作系统的课上,老师也是主要讲解操作系统的原语算法和实现原理,没有用具体语言实现,突然要求我们用一门具体语言实现生产者消费者算法,一时有点举手无措的感觉。但是后来通过自己仔细分析课程设计要求,发现课程设计的算法其实可以分为几个模块,并且每个模块都有很大的联系,比如生产者的实现和消费的实现就是信号量的操作不同,于是自己下去后通过仔细学习关于生产者消费者算法的实现和机制,终于理解了生产者消费者算法实现的难点和关键,并通过在图书馆和网上查阅资料,也对用Linux C实现生产者消费者算法有了一点大概的思路。在后来的实现算法的过程中也遇到了很多的困难,比如在算法中对两个信号量的操作和多线程的实现。通过对Linux C的学习,我也知道了一些Linux C的信号量操作函数和信号量上锁函数,还有多线程操作中的创建线程和销毁线程的函数,通过认真学习相关函数的调用方法和参数传递方法,终于解决了设计中的困难。通过这次课程设计,自己也是受益匪浅,因为平时学到的大部分都是理论知识,而课程设计就是将我们的理论应用到实践的过程,通过这个过程,也让我们锻炼了自己的动手能力,也加深了我们对理论知识的理解,提高了我们对操作系统这门课程的认识和理解,也加强了我们的学习效果。 附录:源程序#include #include #include #include #include #define N 2 / 消费者或者生产者的数目#define M 10 / 缓冲数目int in = 0; / 生产者放置产品的位置int out = 0; / 消费者取产品的位置int buffM = 0; / 缓冲初始化为0, 开始时没有产品sem_t empty_sem; / 同步信号量, 当满了时阻止生产者放产品sem_t full_sem; / 同步信号量, 当没产品时阻止消费者消费pthread_mutex_t mutex; / 互斥信号量, 一次只有一个线程访问缓冲int product_id = 0; /生产者idint prochase_id = 0; /消费者id/* 打印缓冲情况 */void print()int i;for(i = 0; i M; i+) printf(%d , buffi);printf(n);/* 生产者方法 */ void *product()int id = +product_id;while(1) / 用sleep的数量可以调节生产和消费的速度,便于观察 sleep(1); /sleep(1); sem_wait(&empty_sem); pthread_mutex_lock(&mutex); in = in % M; printf(product%d in %d. like: t, id, in); buffin = 1; print(); +in; pthread_mutex_unlock(&mutex); sem_post(&full_sem); /* 消费者方法 */void *prochase()int id = +prochase_id;while(1) / 用sleep的数量可以调节生产和消费的速度,便于观察 sleep(1);/sleep(1); sem_wait(&full_sem); pthread_mutex_lock(&mutex); out = out % M; printf(prochase%d in %d. like: t, id, out); buffout = 0; print(); +out; pthread_mutex_unlock(&mutex); sem_post(&empty_sem);int main()pthread_t id1N;pthread_t id2N;int i;int retN;/ 初始化同步信号量int ini1 = sem_init(&empty_sem, 0, M); int ini2 = sem_init(&full_sem, 0, 0); if(ini1 & ini2 != 0) printf(sem init failed n); exit(1); /初始化互斥信号量 int ini3 = pthread_mutex_init(&mutex, NULL);if(ini3 != 0) printf(mutex init failed n); exit(1); / 创建N个生产者线程for(i = 0; i N; i+) reti = pthread_create(&id1i, NULL, product, (void *)(&i); if(reti != 0) printf(product%d creation failed n, i); exit(1); /创建N个消费者线程for(i = 0; i N; i+) reti = pthread_create(&id2i, NULL, prochase, NULL); if(reti != 0) printf(prochase%d creation failed n, i); exit(1); /销毁线程for(i = 0; i N; i+) pthread_join(id1i,NULL); pthread_join(id2i,NULL);exit(0); 党的基层组织建设有了新突破,党的作风建设有了新加强,为全镇发展经济、提高人民生活永平提供了坚实基础和强大动力carried out; 4) for spring hangers (included simple spring, hangers and constant support hangers) it should also be recognized as setting and locking of loads. 5) check the surface quality, folded layering and without cracks, rust and other defects. 5) after completion of the test and control drawing number one by one, by series baled. Color alloy steel parts, the parts marking installation location and rotation about the direction you want. 7.3.14. hangers installation 7.3.14.1 hanger layout a. a clear design of hanger should be installed strictly in accordance with the drawings and designs shall not be installed wrong, missing, etc. B. own arrangement of piping sup
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年在线销售合作合同书范本
- 长期金融咨询服务合同模板
- 店面接盘协议书格式
- 长期供货协议样本
- 工业产品购销合同模板
- 劳动关系解除协议
- 个人参与创业团队入股协议
- 建筑工程清包工作合同参考
- 2023年高考地理第三次模拟考试卷(江苏B卷)(解析版)
- 货物分期付款购买协议样本
- 中国历史文化知识竞赛100题(满分必刷)
- MOOC 药物分析-中国药科大学 中国大学慕课答案
- MOOC 市场调查与研究-南京邮电大学 中国大学慕课答案
- 新版中日交流标准日本语中级词汇表.上册
- (2024年)互联网医院整体方案介绍课件
- 工程造价及竣工结算投标方案(技术标)
- 医保执法三项制度
- 未来科技与艺术的交融
- 2023年碳素材料行业分析报告及未来五至十年行业发展报告
- 牧原人才测评试题及答案
- (高清版)DZT 0216-2020 煤层气储量估算规范
评论
0/150
提交评论