操作系统实验报告生产者与消费者问题模拟
- 格式:doc
- 大小:150.50 KB
- 文档页数:8
操作系统课程设计一.实验目标完成N个生产者和M个消费者线程之间的并发控制,N、M不低于30,数据发送和接收缓冲区尺寸不小于20个(每个产品占据一个)。
其中生产者线程1、3、5、7、9生产的产品供所有奇数编号的消费者线程消费,只有所有奇数编号的消费者线程都消费后,该产品才能从缓冲区中撤销。
其中生产者线程2、4、6、8、10生产的产品所有偶数编号的消费者线程都可消费,任一偶数编号消费者线程消费该消息后,该产品都可从缓冲区中撤销。
其中11-20号生产者线程生产的产品仅供对应编号的消费者线程消费。
其他编号生产者线程生产的产品可由任意的消费者线程消费。
每个生产线程生产30个消息后结束运行。
如果一个消费者线程没有对应的生产者线程在运行后,也结束运行。
所有生产者都停止生产后,如果消费者线程已经没有可供消费的产品,则也退出运行。
二.实验原理2.1原理生产者与消费者线程采用posix互斥锁机制进行互斥进入各自的代码段,只有采用互斥锁临界区代码段才可以不被打扰的执行;同步机制采用的是posix条件变量pthread_cond_wait和pthraed_cond_signal进行同步的。
线程间的通信采用的是共享内存机制。
(注:所有的共享内存块是在进程里建立的,线程只需链接上各自的共享内存块即可,每一块共享内存的大小是100). 在这里共享内存设置成一个100的数组。
具体实施:(1)为1.3.5.7.9建立一个共享内存1号,1.3.5.7.9生产者线程生产的产品都放入这块共享内存缓冲区,所有奇数的消费者线程要消费的话,只需在消费者线程中链接上这块共享内存,就可以直接消费1.3.5.7.9生产者线程生产的产品。
(2)为2.4.6.8.10建立一块共享内存2号。
2.4.6.8.10生产的产品都放入2号共享内存缓冲区,所有的偶数的消费者线程只要链接上2号缓冲区,就可以消费2.4.6.8.10生产的产品。
当偶数消费者线程消费产品后,产品即可从缓冲区撤销,方法是在消费线程里将消费的产品在共享内存数组里置0。
模拟生产者和消费者进程一、实验内容模拟实现用同步机构避免发生进程执行时可能出现的与时间有关的错误。
二、实验目的进程是程序在一个数据集合上运行的过程,进程是并发执行的,也即系统中的多个进程轮流地占用处理器运行。
我们把若干个进程都能进行访问和修改的那些变量称为公共变量。
由于进程是并发地执行的,所以,如果对进程访问公共变量不加限制,那么就会产生“与时间有关”的错误,即进程执行后所得到的结果与访问公共变量的时间有关。
为了防止这类错误,系统必须要用同步机构来控制进程对公共变量的访问。
一般说,同步机构是由若干条原语——同步原语——所组成。
本实习要求学生模拟PV操作同步机构的实现,模拟进程的并发执行,了解进程并发执行时同步机构的作用。
三、实验题目模拟PV操作同步机构,且用PV操作解决生产者——消费者问题。
[提示]:(1) PV操作同步机构,由P操作原语和V操作原语组成,它们的定义如下:P操作原语P (s):将信号量s减去1,若结果小于0,则执行原语的进程被置成等待信号量s的状态。
V操作原语V (s):将信号量s加1,若结果不大于0,则释放一个等待信号量s的进程。
这两条原语是如下的两个过程:procedure p (var s: semaphore);begin s: = s-1;if s<0 then W (s)end {p}procedure v (var s: semaphore);egin s: = s+1;if s 0 then R (s)end {v}其中W(s)表示将调用过程的进程置为等待信号量s的状态;R(s)表示释放一个等待信号量s的进程。
在系统初始化时应把semaphore定义为某个类型,为简单起见,在模拟实习中可把上述的semaphore直接改成integer。
(2) 生产者——消费者问题。
假定有一个生产者和一个消费者,生产者每次生产一件产品,并把生产的产品存入共享缓冲器以供消费者取走使用。
第1篇一、实验目的1. 加深对进程概念的理解,明确进程和程序的区别。
2. 进一步认识并发执行的实质。
3. 验证用信号量机制实现进程互斥的方法。
4. 验证用信号量机制实现进程同步的方法。
二、实验环境1. 操作系统:Windows 102. 编程语言:C语言3. 开发工具:Visual Studio三、实验内容1. 生产者和消费者模型介绍生产者和消费者模型是操作系统中常见的一种并发控制模型,用于解决多个进程之间的同步和互斥问题。
在该模型中,生产者负责生成数据,消费者负责消费数据。
生产者和消费者通过共享资源(如缓冲区)进行通信。
2. 实验设计(1)环形缓冲区为了实现生产者和消费者的同步,我们设计了一个环形缓冲区,由若干个大小相等的缓冲块组成。
每个缓冲块可以容纳一个产品。
环形缓冲区的指针分别指向当前的第一个空缓冲块和第一个满缓冲块。
(2)信号量为了实现进程互斥和同步,我们使用了三个信号量:① 公用信号量:用于实现临界区互斥,初始值为1。
② 生产者私用信号量:用于实现生产者与消费者之间的同步,初始值为0。
③ 消费者私用信号量:用于实现生产者与消费者之间的同步,初始值为0。
(3)生产者进程生产者进程负责生成数据,并将数据存入环形缓冲区。
当环形缓冲区满时,生产者进程等待;当环形缓冲区有空位时,生产者进程继续生成数据。
(4)消费者进程消费者进程负责从环形缓冲区中取出数据并消费。
当环形缓冲区空时,消费者进程等待;当环形缓冲区有数据时,消费者进程继续消费数据。
3. 实验步骤(1)创建生产者进程和消费者进程。
(2)初始化信号量。
(3)运行生产者进程和消费者进程。
(4)按任意键停止程序,显示当前系统的各个参数的值。
四、实验结果与分析1. 实验结果通过运行实验程序,我们可以观察到生产者和消费者进程的运行情况。
当按下任意键停止程序时,程序将显示当前系统的各个参数的值,包括环形缓冲区的空位数量、生产者和消费者的状态等。
2. 分析(1)互斥:通过公用信号量实现生产者和消费者对环形缓冲区的互斥访问,防止了同时操作缓冲区的问题。
#include <stdio.h>#include <malloc.h>int processnum=0;struct pcb{int flag;int numlabel;char product;char state;struct pcb* processlink;}*exe=NULL,*over=NULL;typedef struct pcb PCB;PCB* readyhead=NULL,*readytail=NULL;PCB* consumerhead=NULL,*consumertail=NULL; PCB* producerhead=NULL,*producertail=NULL;int productnum=0;int buffersize=100;int full=0,empty=buffersize;char buffer[100];int bufferpoint=0;void linkqueue(PCB* process,PCB**tail);PCB* getq(PCB* head,PCB**tail);bool hasElement(PCB* pro);void display(PCB* p);void linklist(PCB* p,PCB* listhead);void freelink(PCB *linkhead);bool processproc();bool waitempty();bool waitfull();void signalempty();void signalfull();void producerrun();void comsuerrun();bool hasElement(PCB* pro);void linklist(PCB* p,PCB* listhead){PCB* cursor=listhead;while(cursor->processlink!=NULL){cursor=cursor->processlink;}cursor->processlink=p;}void freelink(PCB* linkhead){PCB* p;while(linkhead!=NULL){p=linkhead;linkhead=linkhead->processlink;free(p);}}void linkqueue(PCB* process,PCB** tail){if((*tail)!=NULL){(*tail)->processlink=process;(*tail)=process;}else{printf("队列未初始化!");}}PCB* getq(PCB* head,PCB** tail){PCB* p;p=head->processlink;if(p!=NULL){head->processlink=p->processlink;p->processlink=NULL;if(head->processlink==NULL)(*tail)=head;}elsereturn NULL;return p;}bool processproc(){int i,f,num;char ch;PCB*p=NULL;PCB** p1=NULL;printf("\n请输入希望产生的进程个数?");scanf("%d",&num);getchar();//if(num>=100){//printf("您怎么要产生这么多进程! Demands Denied!");//return false;//}for(i=0;i<num;i++){printf("\n请输入您要产生的进程:输入1为生产者进程:输入2为消费者进程\n");scanf("%d",&f);getchar();p=(PCB*)malloc(sizeof(PCB));if(!p){printf("内存分配失败");return false;}p->flag=f;processnum++;p->numlabel=processnum;p->state='w';p->processlink=NULL;if(p->flag==1){printf("您要产生的进程是生产者,它是第%d个进程。
操作系统实验报告——生产者和消费者问题姓名:学号:班级:一、实验内容1、模拟操作系统中进程同步和互斥;2、实现生产者和消费者问题的算法实现;二、实验目的1、熟悉临界资源、信号量及PV操作的定义与物理意义;2、了解进程通信的方法;3、掌握进程互斥与进程同步的相关知识;4、掌握用信号量机制解决进程之间的同步与互斥问题;5、实现生产者-消费者问题,深刻理解进程同步问题;三、实验题目在Windows操作系统下用C语言实现经典同步问题:生产者—消费者,具体要求如下:(1)一个大小为10的缓冲区,初始状态为空。
(2)2个生产者,随机等待一段时间,往缓冲区中添加数据,若缓冲区已满,等待消费者取走数据之后再添加,重复10次。
页脚内容1(3)2个消费者,随机等待一段时间,从缓冲区中读取数据,若缓冲区为空,等待生产者添加数据之后再读取,重复10次。
四、思想本实验的主要目的是模拟操作系统中进程同步和互斥。
在系统进程并发执行异步推进的过程中,由于资源共享和进程间合作而造成进程间相互制约。
进程间的相互制约有两种不同的方式。
(1)间接制约。
这是由于多个进程共享同一资源(如CPU、共享输入/输出设备)而引起的,即共享资源的多个进程因系统协调使用资源而相互制约。
(2)直接制约。
只是由于进程合作中各个进程为完成同一任务而造成的,即并发进程各自的执行结果互为对方的执行条件,从而限制各个进程的执行速度。
生产者和消费者是经典的进程同步问题,在这个问题中,生产者不断的向缓冲区中写入数据,而消费者则从缓冲区中读取数据。
生产者进程和消费者对缓冲区的操作是互斥,即当前只能有一个进程对这个缓冲区进行操作,生产者进入操作缓冲区之前,先要看缓冲区是否已满,如果缓冲区已满,则它必须等待消费者进程将数据取出才能写入数据,同样的,消费者进程从缓冲区读取数据之前,也要判断缓冲区是否为空,如果为空,则必须等待生产者进程写入数据才能读取数据。
在本实验中,进程之间要进行通信来操作同一缓冲区。
实验报告第页专业_______软件工程_____ 班级_________ 学号_____ 姓名实验日期:年月日报告退发(订正、重做)课程实验名称生产者与消费者问题、读者—写者问题一、实验目的1. 实现生产者消费者问题模拟2. 进一步掌握P,V如何解决同步和互斥问题二、实验环境1. Windows或Linux平台2. Eclipse、Visual Studio 2005或GCC三、实验内容、步骤和结果分析实验内容:实现生产者消费者问题模拟,显示每次添加和读取数据时缓冲区的状态,生产者和消费者可用线程模拟。
1.一个大小为10的缓冲区,初始为空。
2. 五个生产者:若缓冲区可以加入数据,则示意进入生产过程(打印出生产者ID),往缓冲区添加数据,随机等待一段时间。
若缓冲区已满,等待消费者取走数据后再添加。
3. 五个消费者:若缓冲区可以读取数据,则示意进入消费过程(打印出消费者ID),从缓冲区读取数据,随机等待一段时间;若缓冲区为空,等待生产者添加数据后再读取。
四、讨论(说明实验过程中遇到的问题及解决办法;未解决/需进一步研讨的问题或建议新实验方法等)(请利用实验二中所给的各个版本信号量类来完成实验三。
若选用Windows平台,要求一定要选用这三个文件夹中的某个信号量类Semaphore来完成实验,否则实验报告视为缺交;若选用Linux平台,也要求参照已给出的三个版本的Semaphore类的接口,先定义一个Linux版本的C++类class Semaphore,并在该类基础上完成实验,提交实验报告时请附上自定义的Semaphore类。
读者—写者问题:#include<windows.h>#include"semaphore.h"#include"thread.h"#include<iostream>using namespace std;Semaphore rmutex(1);Semaphore wmutex(1);int count=0;unsigned int WINAPI Reader(void *p){while(TRUE){rmutex.P();count++;rmutex.V();if(count == 1)wmutex.P();cout << GetCurrentThreadId() << "reading the student's table"<<endl;rmutex.P();count--;rmutex.V();if(count == 0)wmutex.V();Sleep(rand()%1000);}}unsigned int WINAPI Writer(void *p){while(TRUE){wmutex.P();cout << GetCurrentThreadId() << "writting the student's table"<<endl;wmutex.V();Sleep(rand()%1000);}}int main(){HANDLE hThread[2];hThread[0] = startThread(Reader,NULL);hThread[1] = startThread(Writer,NULL);::WaitForMultipleObjects(2,hThread,TRUE,INFINITE);CloseHandle(hThread[0]);CloseHandle(hThread[1]);return 0;}生产者与消费者问题:#include<windows.h>#include"semaphore.h"#include"thread.h"#include<iostream>using namespace std;Semaphore full(5);Semaphore empty(5);Semaphore mutex(1);int count=0;unsigned int WINAPI Producer(void *p){while(TRUE){empty.P();mutex.P();cout << GetCurrentThreadId() << " produce!"<<endl;mutex.V();full.V();Sleep(rand()%1000);}}unsigned int WINAPI Consumer(void *p){while(TRUE){full.P();mutex.P();cout << GetCurrentThreadId() << " consum!"<<endl;mutex.V();empty.V();Sleep(rand()%1000);}}int main(){HANDLE hThread[2];hThread[0] = startThread(Producer,NULL);hThread[1] = startThread(Consumer,NULL);::WaitForMultipleObjects(2,hThread,TRUE,INFINITE);CloseHandle(hThread[0]);CloseHandle(hThread[1]); return 0;}。
实验报告(学生打印后提交)实验名称: 生产者和消费者问题实验时间: 2023年 5 月 5日●实验人员:●实验目的:掌握基本的同步互斥算法, 理解生产者和消费者模型。
●了解Windows 2023/XP中多线程的并发执行机制, 线程间的同步和互斥。
●学习使用Windows 2023/XP中基本的同步对象, 掌握相应的API●实验环境: WindowsXP + VC++6.0●运用Windows SDK提供的系统接口(API, 应用程序接口)完毕程序的功能。
API是操作系统提供的用来进行应用程序设计的系统功能接口。
使用API, 需要包含对API函数进行说明的SDK头文献, 最常见的就是windows.h实验环节:1.读懂源程序.2.编辑修改源程.......................................实验陈述:1.基础知识:本实验用到几个API函数:CreateThread CreateMutex, WaitForSingleObject, ReleaseMutexCreateSemaphore, WaitForSingleObject, ReleaseSemaphore, ReleaseMutex, nitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection。
这些函数的作用:CreateThread, 功能:创建一个线程, 该线程在调用进程的地址空间中执行。
CreateMutex,功能:产生一个命名的或者匿名的互斥量对象。
WaitForSingleObject(相应p操作)锁上互斥锁, ReleaseMutex(相应v操作)打开互斥锁.。
CreateSemaphore, 创建一个命名的或者匿名的信号量对象。
信号量可以看作是在互斥量上的一个扩展。
WaitForSingleObject, 功能:使程序处在等待状态, 直到信号量(或互斥量)hHandle出现或者超过规定的等待最长时间, 信号量出现指信号量大于或等于1, 互斥量出现指打开互斥锁。
操作系统上机实验报告实验名称:生产者与消费者问题模拟实验目的:通过模拟生产者消费者问题理解进程或线程之间的同步与互斥。
实验内容:1、设计一个环形缓冲区,大小为10,生产者依次向其中写入1到20,每个缓冲区中存放一个数字,消费者从中依次读取数字。
2、相应的信号量;3、生产者和消费者可按如下两种方式之一设计;(1)设计成两个进程;(2)设计成一个进程内的两个线程。
4、根据实验结果理解信号量的工作原理,进程或线程的同步\互斥关系。
实验步骤及分析:一.管道(一)管道定义所谓管道,是指能够连接一个写进程和一个读进程的、并允许它们以生产者—消费者方式进行通信的一个共享文件,又称为pipe文件。
由写进程从管道的写入端(句柄1)将数据写入管道,而读进程则从管道的读出端(句柄0)读出数据。
(二)所涉及的系统调用1、pipe( )建立一无名管道。
系统调用格式pipe()参数定义int pipe();int [2];其中,[1]是写入端,[0]是读出端。
该函数使用头文件如下:#include <unistd.h>#inlcude <signal.h>#include <stdio.h>2、read( )系统调用格式:read(fd,buf,nbyte)功能:从fd所指示的文件中读出nbyte个字节的数据,并将它们送至由指针buf所指示的缓冲区中。
如该文件被加锁,等待,直到锁打开为止。
参数定义:int read(fd,buf,nbyte);int fd;char *buf;unsigned nbyte;3、write( )系统调用格式read(fd,buf,nbyte)功能:把nbyte 个字节的数据,从buf所指向的缓冲区写到由fd所指向的文件中。
如文件加锁,暂停写入,直至开锁。
参数定义同read( )。
(三)参考程序#include <unistd.h>#include <signal.h>#include <stdio.h>int pid1,pid2;main( ){int fd[2];char outpipe[100],inpipe[100];pipe(fd); /*创建一个管道*/while ((pid1=fork( ))==-1);if(pid1==0){lockf(fd[1],1,0);/*把串放入数组outpipe中*/sprintf(outpipe,"child 1 is using pipe!");/*向管道写长为50字节的串*/write(fd[1],outpipe,50);sleep(5); /*自我阻塞5秒*/lockf(fd[1],0,0);exit(0);}else{while((pid2=fork( ))==-1);if(pid2==0){lockf(fd[1],1,0); /*互斥*/sprintf(outpipe,"child 2 is using pipe!");write(fd[1],outpipe,50);sleep(5);lockf(fd[1],0,0);exit(0);}else{wait(0); /*同步*/read(fd[0],inpipe,50);/*从管道中读长为50字节的串*/printf("%s\n",inpipe);wait(0);read(fd[0],inpipe,50);printf("%s\n",inpipe);exit(0);}}}编写过程:运行结果:二、信号机制(一)信号的基本概念每个信号都对应一个正整数常量(称为signal number,即信号编号。
第一篇:操作系统实验报告经典生产者—消费者问题实验二经典的生产者—消费者问题一、目的实现对经典的生产者—消费者问题的模拟,以便更好的理解经典进程同步问题。
二、实验内容及要求编制生产者—消费者算法,模拟一个生产者、一个消费者,共享一个缓冲池的情形。
1、实现对经典的生产者—消费者问题的模拟,以便更好的理解此经典进程同步问题。
生产者-消费者问题是典型的PV 操作问题,假设系统中有一个比较大的缓冲池,生产者的任务是只要缓冲池未满就可以将生产出的产品放入其中,而消费者的任务是只要缓冲池未空就可以从缓冲池中拿走产品。
缓冲池被占用时,任何进程都不能访问。
2、每一个生产者都要把自己生产的产品放入缓冲池,每个消费者从缓冲池中取走产品消费。
在这种情况下,生产者消费者进程同步,因为只有通过互通消息才知道是否能存入产品或者取走产品。
他们之间也存在互斥,即生产者消费者必须互斥访问缓冲池,即不能有两个以上的进程同时进行。
三、生产者和消费者原理分析在同一个进程地址空间内执行两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
消费者线程从缓冲区中获得物品,然后释放缓冲区。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放一个空缓冲区。
当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻挡,直到新的物品被生产出来。
四、生产者与消费者功能描述:生产者功能描述:在同一个进程地址空间内执行两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。
消费者功能描述:消费者线程从缓冲区获得物品,然后释放缓冲区,当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。
五、实验环境操作系统环境:Windows 系统。
编程语言:C#。
一、目的和要求在采用多道程序设计的系统中,往往有若干个进程并发执行。
进程之间存在相互制约关系,本实验模拟在单处理器情况下的进程并发执行过程中,如何利用信号量机制实现并发进程的同步和互斥,帮助学生加深了解信号量机制、进程的同步和互斥。
二、实验内容利用高级语言模拟生产者-消费者算法算法。
分析:本算法需要解决以下问题1、生产者和消费者不能同时进入缓冲池2、缓冲池已满时,生产者不能再投放3、缓冲池为空时,消费者不能消费问题解决方法1、使用互斥变量mutex,为1时,可以进入,为0不可进入,通过lock()和unlock()实现锁定和解锁2、通过数组pbuffer[n]和pnum[n]实现生产者队列,分别记录生产者的商品以及生产者序号。
生产者进程产生时判断队列是否有进程等待,当缓冲区满时,进入队列,出现空区时,队列优先进入。
3、通过数组cnum[n]实现消费者队列,用于记录消费者编号,消费者进程产生时判断队列是否有进程等待,当缓冲区空时,进入队列,出现非空时,队列优先进入。
三、算法设计与实现主流程图示:生产者功能流程图示:消费者功能流程图示:实验函数void main();void run();void jiance(int mutex);//判断当前缓冲区是否被占用void lock(int mutex);//将缓冲池锁定mutex置为1void unlock(int mutex);//释放缓冲池mutex置为0void producer();//生产者进程int pro();//生产者随机生产的产品int pisempty();//判断生产者队列是否为空int bisempty();//判断缓冲池的各个缓冲区是否都已经被填满void input(int pn,int nextp);//在生产者队列为空的条件下,进行放入缓冲池的操作void input2();//生产者队列不为空时,排队进入缓冲池void inpb(int pn,int nextp);//生产者队列为空时进入生产者队列void customer();//消费者进程int cisempty();//判断消费者队列是否为空void outb(int cn);//消费者队列为空时,进入消费者队列void output2();//消费者队列不为空时,排队消费产品void output(int cn);//取出缓冲池商品,进行消费的操作四、运行界面。
中南大学操作系统实验报告实验内容:Java多线程模拟生产者消费者问题实验时间:2014年5月指导老师:胡小龙老师姓名:代巍班级:信安1201班学号:**********一、实验目的对操作系统的整体进行一个模拟,通过实践加深对各个部分的管理功能的认识,还能进一步分析各个部分之间的联系,最后达到对完整系统的理解。
可以提高运用操作系统知识解决实际问题的能力;锻炼实际的编程能力,要达到以下要求。
(1)掌握进程(线程)的同步与互斥。
(2)掌握生产者消费者问题的实现方法。
(3)掌握多线程编程方法。
二、实验内容实现生产者消费者问题。
(1)假设循环缓冲队列共有多个缓冲单元。
(2)生产者线程的工作:生产出一个产品(即产生一个产品编号),按顺序往缓冲队列中“空”的缓冲单元放产品。
(3)消费者线程与的工作:从缓冲队列装有产品的缓冲单元中取出一个产品(即产品编号)。
(4)保证两个线程间的互斥和同步(5)在界面上打印缓冲队列的变化情况三、实验原理(1)生产者—消费者问题是一种同步问题的抽象描述。
(2)计算机系统中的每个进程都可以消费或生产某类资源。
当系统中某一进程使用某一资源时,可以看作是消耗,且该进程称为消费者。
(3)而当某个进程释放资源时,则它就相当一个生产者。
模式还需要有一个缓冲区处于生产者和消费者之间,作为一个中介。
生产者把数据放入缓冲区,而消费者从缓冲区取出数据。
大概的结构如下图。
四、实验思想概述在操作系统中,线程有时被称为轻量级进程,是CPU使用的基本单位,它与属于同一进程的其他进程共享其他代码段、数据段和其他操作系统资源。
在Java中,线程的建立有两种方法:继承Thread类和实现Runnable接口。
其中,采用实现Runnable接口建立线程的好处是允许同时继承其他类从而实现多继承,并且在Java中,可采用synchronized或Object类的方法wait(),notify(),notifyAll()来实现多线程同步。
生产者-消费者实验1.1实验目的和要求1.1.1实验目的操作系统的基本控制和管理控制都围绕着进程展开,其中的复杂性是由于支持并发和并发机制而引起的。
自从操作系统中引入并发程序设计后,程序的执行不再是顺序的,一个程序未执行完而另一个程序便已开始执行,程序外部的顺序特性消失,程序与计算不再一一对应。
并发进程可能是无关的,也可能是交互的。
然而,交互的进程共享某些变量,一个进程的执行可能会影响其他进程的执行结果,交互的并发进程之间具有制约关系、同步关系。
其中典型模型便是生产者-消费者模型。
本实验通过编写和调试生产者-消费者模拟程序,进一步认识进程并发执行的实质,加深对进程竞争关系,协作关系的理解,掌握使用信号量机制与P、V操作来实现进程的同步与互斥。
1.1.2实验要求1.用高级语言编写一个程序,模拟多个生产者进程和多个消费者进程并发执行,并采用信号量机制与P、V操作实现进程间同步与互斥。
2.撰写实验报告,报告应包含以下内容:(1)实验目的;(2)实验内容;(3)设计思路;(4)程序流程图;(5)程序中主要数据结构和函数说明;(6)带注释的源程序代码;(7)程序运行结果及分析;(8)实验收获与体会。
1.2预备知识1.2.1生产者—消费者问题生产者—消费者问题表述如下:如图 3.1所示,有n个生产者和m个消费者,连接在具有k个单位缓冲区的有界环状缓冲上,故又称有界缓冲问题。
生产者不断生成产品,只要缓冲区未满,生产者进程pi所生产的产品就可投入缓冲区;类似的,只要缓冲区非空,消费者进程cj就可以从缓冲区取走并消耗产品。
图 3.1 生产者—消费者问题示意图著名的生产者—消费者问题(producer-consumer problem)是计算机操作系统中并发进程内在关系的一种抽象,是典型的进程同步问题。
在操作系统中,生产者进程可以是计算进程、发送进程,而消费者进程可以是打印进程、接收进程等,解决好生产者—消费者问题就解决了一类并发进程的同步问题。
实验一生产者和消费者问题1、程序流程图2、源代码#include <windows.h>#include <iostream>const unsigned short SIZE_OF_BUFFER = 10;unsigned short ProductID = 0;unsigned short ConsumeID = 0;unsigned short in = 0;unsigned short out = 0;int g_buffer[SIZE_OF_BUFFER];bool g_continue = true;HANDLE g_hMutex;HANDLE g_hFullSemaphore;HANDLE g_hEmptySemaphore;DWORD WINAPI Producer(LPVOID);DWORD WINAPI Consumer(LPVOID);int main(){ g_hMutex = CreateMutex(NULL,FALSE,NULL);g_hFullSemaphore = CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL);g_hEmptySemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);const unsigned short PRODUCERS_COUNT = 3;const unsigned short CONSUMERS_COUNT = 1;const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT;HANDLE hThreads[PRODUCERS_COUNT];DWORD producerID[CONSUMERS_COUNT];DWORD consumerID[THREADS_COUNT];for (int i=0;i<PRODUCERS_COUNT;++i){hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);if (hThreads[i]==NULL) return -1;}for ( i=0;i<CONSUMERS_COUNT;++i){hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]);if (hThreads[i]==NULL) return -1;}while(g_continue){if(getchar()){ //按回车后终止程序运行g_continue = false;}}return 0;}void Produce(){ std::cerr << "Producing " << ++ProductID << " ... ";std::cerr << "Succeed" << std::endl;}void Append(){ std::cerr << "Appending a product ... ";g_buffer[in] = ProductID;in = (in+1)%SIZE_OF_BUFFER;std::cerr << "Succeed" << std::endl;for (int i=0;i<SIZE_OF_BUFFER;++i){std::cout << i <<": " << g_buffer[i];if (i==in) std::cout << " <-- 生产";if (i==out) std::cout << " <-- 消费";std::cout << std::endl;}}void Take(){ std::cerr << "Taking a product ... ";ConsumeID = g_buffer[out];out = (out+1)%SIZE_OF_BUFFER;std::cerr << "Succeed" << std::endl;for (int i=0;i<SIZE_OF_BUFFER;++i){std::cout << i <<": " << g_buffer[i];if (i==in) std::cout << " <-- 生产";if (i==out) std::cout << " <-- 消费";std::cout << std::endl; }}void Consume(){ std::cerr << "Consuming " << ConsumeID << " ... ";std::cerr << "Succeed" << std::endl;}DWORD WINAPI Producer(LPVOID lpPara){ while(g_continue){WaitForSingleObject(g_hFullSemaphore,INFINITE);WaitForSingleObject(g_hMutex,INFINITE);Produce();Append();Sleep(1500);ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hEmptySemaphore,1,NULL);}return 0;}DWORD WINAPI Consumer(LPVOID lpPara){ while(g_continue){WaitForSingleObject(g_hEmptySemaphore,INFINITE);WaitForSingleObject(g_hMutex,INFINITE);Take();Consume();Sleep(1500);ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hFullSemaphore,1,NULL);}return 0;}3、实验结果3、实验心得通过做生产者消费者问题这个实验,让我更加明确了两者之间的联系和基本的同步互斥算法,了解多线程并发执行机制是怎样的,线程间的同步和互斥又是怎样的,还有缓冲区的在其中作用是什么。
操作系统课程设计实验报告实验名称:生产者消费者问题姓名/学号:一、实验目的以生产者和消费者问题为例,学习Linux和Windows下进程通信、同步机制的具体实现方法,主要是信号量和共享内存。
熟悉相关系统API的用法。
二、实验内容使用共享内存和信号量机制来实现多个生产者/消费者进程间的通信和同步。
要求在Linux和Windows下分别实现。
缓冲区大小为3,初始为空。
2个生产者,随机等待一段时间,往缓冲区添加数据,重复6次。
3个消费者,重复4次。
三、实验环境Ubuntu 10.10 , GCC; Windows 7, VC 6.0;四、程序设计与实现1. Linux下:(1) 数据结构:a. 共享内存定义为一个结构,使得其数据成员更清晰且操作变得简单。
b. 共享缓冲区采用循环队列的数据结构,由上面的结构struct buf { int start; int end; int info[BUF_NUM]; }维护。
其中start为队头指针,end为队尾指针,info为数据区域。
(2) 算法:大致由三个模块组成:a.主程序(main):i.创建信号量、共享内存并进行初始化ii.创建生产者、消费者进程,生产者执行pro_fun(),消费者执行con_fun()iii.等待所有子进程的结束iv.删除信号量、共享内存b.生产者进程(pro_fun):i.通过key获得信号量、共享内存的ID,将内存添加到自己的地址空间ii.P(empty),P(mutex),Add(data),V(mutex),V(full)iii.解除和共享内存的关联c.消费者进程(con_fun):i.通过key获得信号量、共享内存的ID,将内存添加到自己的地址空间ii.P(full),P(mutex),Add(data),V(mutex),V(empty)iii.解除和共享内存的关联d.循环队列部分:加入数据:info[end] = value; end = (end + 1) % 3;取出数据:temp = info[start]; info[start] = 0; (start = start + 1)%3; return temp;(3) 程序流程图:a. 主函数:b. 生产者进程:c. 消费者进程和生产者类似4. Windows 下:(1) 数据结构:和Linux大致相同(2) 算法:a. 创建的子进程调用正在执行的文件本身,通过main函数的参数区分主进程和生产者、消费者进程。
矿产资源开发利用方案编写内容要求及审查大纲
矿产资源开发利用方案编写内容要求及《矿产资源开发利用方案》审查大纲一、概述
㈠矿区位置、隶属关系和企业性质。
如为改扩建矿山, 应说明矿山现状、
特点及存在的主要问题。
㈡编制依据
(1简述项目前期工作进展情况及与有关方面对项目的意向性协议情况。
(2 列出开发利用方案编制所依据的主要基础性资料的名称。
如经储量管理部门认定的矿区地质勘探报告、选矿试验报告、加工利用试验报告、工程地质初评资料、矿区水文资料和供水资料等。
对改、扩建矿山应有生产实际资料, 如矿山总平面现状图、矿床开拓系统图、采场现状图和主要采选设备清单等。
二、矿产品需求现状和预测
㈠该矿产在国内需求情况和市场供应情况
1、矿产品现状及加工利用趋向。
2、国内近、远期的需求量及主要销向预测。
㈡产品价格分析
1、国内矿产品价格现状。
2、矿产品价格稳定性及变化趋势。
三、矿产资源概况
㈠矿区总体概况
1、矿区总体规划情况。
2、矿区矿产资源概况。
3、该设计与矿区总体开发的关系。
㈡该设计项目的资源概况
1、矿床地质及构造特征。
2、矿床开采技术条件及水文地质条件。