北邮操作系统消费者与生产者实验报告.doc_第1页
北邮操作系统消费者与生产者实验报告.doc_第2页
北邮操作系统消费者与生产者实验报告.doc_第3页
北邮操作系统消费者与生产者实验报告.doc_第4页
北邮操作系统消费者与生产者实验报告.doc_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

操作系统实验课程报告 课题: 消费者与生产者实验姓 名 张涛 学 院 计算机学院 班 级 2011211311 学 号 2011211419 2013年 12月 14日1实验目的:1)理解线程同步的思想和方法,学会用线程同步解决临界区问题,本次实验解决生产者消费者问题2了解windows系统或linux系统下中信号量的使用方法。2实验预备内容(1) 阅读Linux的sched.h源码文件,加深对进程管理概念的理解。这个文件长达2616行,这里截取第12211548行抄录在实验报告最后,即结构体task_struct,地位相当于PCB。下面对几个比较重要的参数,结合本人的了解 以及 网上查阅的资料 做一点解释。中括号内的数字为代码行号,下同。volatilelongstate:【1222】进程状态字,表示进程当前的状态(运行、就绪、等待、僵死、暂停、交换),分别对应已定义好的常量;TASK_RUNING:正在运行或可运行状态;TASK_INTERRUPTIBLE:可打断睡眠状态;TASK_UNINTERRUPTIBLE:不可打断睡眠状态;TASK_ZOMBLE:僵死状态;TASK_STOPPED:暂停状态;交换状态。void*stack:【1223】进程所使用的栈空间;unsignedintflags:【1225】进程标志(创建、关闭、跟踪、被跟踪、内核dump等),同样对应已定义好的常量;unsignedintrt_priority:【1237】表示本进程的实时优先级;conststructsched_class *sched_class、structsched_entity se:【1239,1240】分别是调度类和调度实体,这两个结构包含了用于任务调度的完整的信息(进程信息、调度策略等);unsignedintpolicy:【1260】进程的调度策略标志,有三种调度标志:SCHED_OTHER:普通进程的调度策略,基于优先权的轮转法;SCHED_FIFO:实时进程的调度策略,基于先进先出的算法;SCHED_RR:实时进程的调度策略,基于优先权的轮询法。structlist_head tasks:【1274】任务队列,为一双向循环链表;intpdeath_signal:【1282】父进程终止时产生的信号;pid_t pid:【1294】进程标识符,操作系统每创建一个新的进程就要为这个新进程分配一个进程控制块(PCB),系统内核通过pid区分这些进程的;structtask_struct *real_parent:【1307】本进程的父进程的PCB;structlist_head children:【1312】本进程的子进程列表;structlist_head ptraced:【1321】本进程正在使用ptrace监视的进程列表;structthread_struct thread:【1375】本进程下属的线程集;structsignal_struct *signal、structsighand_struct *sighand:【1383,1384】分别是进程运行时产生的信号以及信号处理模块。(2) 阅读Linux的pthread.h源码文件,分析线程的创建过程。pthread接口说明#include 1、创建int pthread_create( pthread_t *tid, const pthread_attr_t *attr, void *(* func) (void *), void *arg );attr: 线程属性包括:优先级、初始栈大小,是否应该成为一个守护线程。缺省设置,NULL后面是线程要执行的函数和参数成功返回 02、等待一个给定线程终止int pthread_join( pthread_t tid, void *status);等待线程结束 critiction 可以在进程中使用,mutex只可在进程中使用statues返回等待线程的返回值 multiple definition of _dso_handle/usr/lib/gcc/i486-linux-gnu/4.4.3/crtbegin.o:(.data+0x0): first defined herethreadTest: In function _init:(.init+0x0): multiple definition of _init/usr/lib/gcc/i486-linux-gnu/4.4.3/././././lib/crti.o:(.init+0x0): first defined here/tmp/cchm2SmY.o:(.data+0x0): multiple definition of flagthreadTest:(.data+0x8): first defined here/tmp/cchm2SmY.o: In function threadMe3、得到自身的pidpthread_t pthread_self(void);4、pthread_detach函数int pthread_detach( pthread_t pid );把指定的线程转变为脱离状态一个线程或者是可汇合的(joinable,缺省值),或者是脱离的(detached)。当一个可汇合的线程终止时,它的线程ID和退出状态将留到另一个线程对它调用pthread_join。脱离线程却象守护进程:当它们终止的时,所有相关资源都被释放,我们不能等待它们终止。如果一个线程需要知道另一个线程什么时候终止,那就最好好吃第二个线程的可汇合状态。本函数通常由想让自己脱离的线程调用,如下语句pthread_detach( pthread_self() );5、终止一个线程void pthread_exit( void *statue );指针sttus不能指向局部于调用对象,因为线程终止时这样的对象也消失(3) 阅读Linux的semaphore.h源码文件,分析线程的创建过程。typedef struct sem_t_ * sem_t;PTW32_DLLPORT int _cdecl sem_init (sem_t * sem, int pshared, unsigned int value);PTW32_DLLPORT int _cdecl sem_destroy (sem_t * sem);PTW32_DLLPORT int _cdecl sem_trywait (sem_t * sem);PTW32_DLLPORT int _cdecl sem_wait (sem_t * sem);PTW32_DLLPORT int _cdecl sem_post (sem_t * sem);PTW32_DLLPORT int _cdecl sem_post_multiple (sem_t * sem, int count);PTW32_DLLPORT int _cdecl sem_close (sem_t * sem);PTW32_DLLPORT int _cdecl sem_unlink (const char * name);int sem_init(sem_t *sem,int pshared,unsigned int value)。用于信号量的初始化,第一个参数为信号量的名称,第二个参数为信号量的共享属性,一般设为0(不共享),第三个参数为信号量的初始值。int sem_wait(sem_t *sem)。相当于上面的wait()操作,作用是当信号量的值大于0时,给信号量的值减1,否则会阻塞直至信号量的值大于0。它是一个原子操作。int sem_post(sem_t *sem)。相当于上面的signal()操作,作用是给信号量的值加1。它也是一个原子操作。*/3实验环境此实验采用的是Win8下Microsoft Visual Stdio 2012工程。由于系统不包含semaphore.h,sched.h及pthread.h头文件,所以这些头文件都是从网上FTP资源下载后,加入工程的。程序中加入#pragma comment(lib, pthreadVC2.lib)来调用pthread链接库。文件根目录下已下载pthreadVC2.dll*/4实验步骤A设计思路这个问题是进程同步的经典问题之一,基本思路是设置三个信号量:mutex信号量,用于控制生产者和消费者对于缓冲区的互斥访问;empty信号量,记录当前为空的缓冲区的数目,初始化为所有缓冲区的数目BUF_SIZE;full信号量,记录当前已满的缓冲区的数目,初始化为0。*/一个buffer,一个生产者,一个消费者(1)规则只有buffer为空才能put;只有buffer中有数据才能get;不允许多个put操作同时进行;不允许多个get操作同时进行。这时buffer变成了临界资源,消费者之间需要互斥地使用,生产者之间也需要互斥地使用,消费者和生产者之间也需要互斥地使用,这时设置两个信号量s1,s2实现同步,例外设置S信号,代表buffer这种临界资源,用于互斥,称之为互斥信号量。(2)实现流程p(s1)判断buffer是否空p(s)是否可进行put,是否有其他进程占用bufferputv(s)释放buffer,让其他进程可以使用v(s2)给消费者进程释放一个buffer中有数据的信号p(s2)判断是否有数据p(s)是否可进行get,是否有其他进程占用getv(s)释放buffer,让其他进程可以使用v(s1)给生产者释放一个buffer为空的信号通过3个信号量,实现了消费者和生产者之间同步关系,也保证了在某个时刻只有一个进程使用临界资源buffer。生产者进程的代码结构描述如下:while(true) nextp=produce();wait(empty);wait(mutex);put(nextp);signal(mutex);signal(full); 消费者进程的代码结构描述如下:while(true) wait(full);wait(mutex);nextc=get();signal(mutex);signal(empty);consume(nextc); 这里两个wait语句的次序并不能调换,这是因为如果将两个wait操作即wait(full)和wait(mutex)互换位置,或者将release(mutex)与release(full)互换位置,当缓冲区存满产品时,生产者又生产了一件产品,它欲向缓冲区存放时将在empty上等待,但它已经占有了使用缓冲区的权利。这时消费者要取产品时将停留在mutex上得不到使用缓冲区的权利,导致生产者等待消费者取走产品,而消费者却在等待生产者释放使用缓冲区的权利,这种相互等待永远结束不了。因此进程将会发生死锁。*/B实验代码分析生产者:/* Producer * Produce items and try to put it into the buffer* If the buffer is full, waiting* When produced, we output like that: Producer 2 produced 222* When successfully put, we output: Producer 2 have put product 222 into the buffer after 100 milliseconds* The milliseconds is the timespan from the producer produced the item* When the buffer is full but the producer put the item, an error occurred* (No way it will happen.)*/#define PTIMESPANMAX 5000void* producer(void* params) int id=*(int *)params; while(true) SLEEP(rand()%PTIMESPANMAX); buffer_item rnd=rand(); long begin, end; CLOCK(begin); printf(%ld:t Producer %dt produced %dn, (long)(begin-threadStart), id, rnd); sem_wait(&empty); pthread_mutex_lock(&mutex); (CLOCK(end), insert_item(rnd) ? printf(%ld:t Producer %dt have put %dt after %dt millisecondsn,end-threadStart, id, rnd, end-begin) : printf(%ld:t Producer %dt Report Error!n, end-threadStart, id); pthread_mutex_unlock(&mutex); sem_post(&full); */消费者:/* Consumer* Try to consume items from the buffer* If the buffer is empty, waiting* When try to consume, we output like that: Consumer 3 want to consume* When successfully consumed, we output: Consumer 3 consumed 222 after 100 milliseconds* The milliseconds is the timespan from the consumer try to consume the item* When the buffer is empty but the consumer consumed the item, an error occurred* (No way it will happen.)*/#define CTIMESPANMAX 5000void * consumer(void* params) int id=*(int *)params; while(true) SLEEP(rand()%CTIMESPANMAX); long begin, end; CLOCK(begin); printf(%ld:t Consumer %dt want to consumen, begin-threadStart, id); sem_wait(&full); pthread_mutex_lock(&mutex); buffer_item item=buffercurrentIndex; (CLOCK(end), remove_item(&item) ? printf(%ld:t Consumer %dt consumed %dt after %dt millisecondsn, end-threadStart, id, item, end-begin) : printf(%ld:t Consumer %dt Report Error!n, end-threadStart, id); pthread_mutex_unlock(&mutex); sem_post(&empty); */主函数:int main(int argc, char* argv) srand(unsigned int(time(0); / Init mutex, full and empty pthread_mutex_init(&mutex, NULL); sem_init(&full, 0, BUFFER_SIZE); sem_init(&empty, 0, BUFFER_SIZE); int i=0; / e. No item in the buffer now, so full is full for(i=0; iBUFFER_SIZE; i+) sem_wait(&full); int sleepTime=0; int producerCount=0; int consumerCount=0; printf(How long to sleep before terminating: ); scanf_s(%d, &sleepTime); printf(The number of producer threads: ); scanf_s(%d, &producerCount); printf(The number of consumer threads: ); scanf_s(%d, &consume

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论