VC++学习:用vc实现生产者消费者问题
操作系统实验三 生产者——消费者问题

操作系统实验三:生产者——消费者问题一、基本信息xxx 711103xx 2012年4月29日二、实验目的通过实验,掌握Windows和Linux环境下互斥锁和信号量的实现方法,加深对临界区问题和进程同步机制的理解,同时巩固利用Windows API和Pthread API进行多线程编程的方法。
三、实验内容1. 在Windows操作系统上,利用Win32 API提供的信号量机制,编写应用程序实现生产者——消费者问题。
2. 在Linux操作系统上,利用Pthread API提供的信号量机制,编写应用程序实现生产者——消费者问题。
3. 两种环境下,生产者和消费者均作为独立线程,并通过empty、full、mutex 三个信号量实现对缓冲进行插入与删除。
4. 通过打印缓冲区中的内容至屏幕,来验证应用程序的正确性。
四、实验步骤1. 创建3个信号量:Mutex、Full、Empty2. 主程序创建10个生产者线程和10个消费者线程,之后休眠一段时间3. 生产者线程中,休息一段2s后,生产一个0~10的随机数放入缓冲区里。
利用信号量Mutex产生对缓冲区使用的互斥功能,利用Empty和Full信号量来对缓冲区进行增加项4. 消费者线程中,休息4s时间后,消费一个缓冲区的数据。
利用信号量Mutex产生对缓冲区使用的互斥功能,利用Empty和Full信号量来对缓冲区进行增加项5. 主程序执行一段时间后,结束整个程序五、主要数据结构及其说明产品数量最大值const int MAX_SIZE = 10;缓冲区:int buffer[BUFFER_SIZE];int front; int rear; bool full;三个互斥信号量:HANDLE Mutex; HANDLE Full; HANDLE Empty;有关操作:用WaitForSingleSignal函数可以获得一个Mutex的所有权,类似于P 操作,而ReleaseMutex函数可以释放一个Mutex的所有权,类似于V 操作。
生产者消费者问题模拟实现(z)

int *pcq; //信号量队列指针
} Seamphore;
int producerCongestionQueue[processNum]; //等待信号量 empty
的阻塞队列 int consumerCongestionQueue[processNum]; //等待信
号量 full 的阻塞队列
用信号量机制解决生产者—消费者问题可描述如下:
item B[k];
semaphore empty; empty=k; //可以使用的空缓冲区数
semaphore full; full=0;
//缓冲区内可以使用的产品数
semaphore mutex; mutex=1; //互斥信号量
int in=0; //放入缓冲区指针
号量 s 的阻塞队列中。
(2)V(s):s.value++;若 s.value≤0,则执行 V(s)的进程从等待
信号量 s 的阻塞队列中唤醒头一个进程,然后自己继续执行。若
s.value>0 ,则执行 V(s)
的进程继续执行;
1.2.3 信号量实现互斥
信号量和 PV 操作可用来解决进程互斥问题。为使多个进程能互斥地
append to B[in];
out =
(out+1)%k;
in = (in+1)%k;
V(mutex);
V(mutex);
V(empty);
V(full);
consume();
}
}}
}
Coend
程序中的 P(mutex)和 V(mutex)必须成对出现,夹在两者之间的代码
段是临界区;施加于信号量 empty 和 full 上的 PV 操作也必须成对出
操作系统课程设计生产者-消费者问题附代码

枣庄学院信息科学与工程学院课程设计任务书题目:生产者-消费者问题的实现姓名:学号:专业:计算机科学与技术课程:操作系统指导教师:刘彩霞职称:讲师完成时间:2012年5月----2012 年6月枣庄学院信息科学与工程学院制课程设计任务书及成绩评定目录第1章引言 (1)1.1 设计背景 (1)1.2 问题分类 (1)1.3 解决方案 (1)第2章设计思路及原理 (2)第3章程序详细设计 (3)3.1程序模块设计 (3)3.2程序代码结构 (5)第4章实验结果 (7)第5章实验总结 (8)附录:实验代码 (9)第1章引言1.1 设计背景生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra 提出,用以演示他提出的信号量机制。
在同一个进程地址空间内执行的两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
消费者线程从缓冲区中获得物品,然后释放缓冲区。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。
当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。
1.2 问题分类根据缓冲区的个数、大小以及生产者消费者的个数可以分为以下几类:1.单缓冲区(适合单或多生产消费者);2.环行多缓冲区(或无穷缓冲区)单生产消费者;3.环行多缓冲区多生产消费者;1.3 解决方案1.用进程通信(信箱通信)的方法解决;2.进程消息缓冲通信;3.进程信箱通信;第2章设计思路及原理设计了两个主要函数:生产者函数、消费者函数;设计了三个信号量:full信号量,判断缓冲区是否有值,初值为0;empty信号量,判断缓冲区是否有空缓冲区,初值为缓冲区数;mutex信号量作为互斥信号量,用于互斥的访问缓冲区。
生产者函数通过执行P操作信号量empty减1,判断缓冲区是否有空。
有空则互斥的访问缓冲区并放入数据,然后释放缓冲区,执行V操作,信号量full 加1。
操作系统实验参考代码

目录实验一WINDOWS进程初识 (2)实验二进程管理 (6)实验三进程同步的经典算法 (10)实验四存储管理 (14)试验五文件系统试验 (18)实验有关(参考)代码实验一WINDOWS进程初识1、实验目的(1)学会使用VC编写基本的Win32 Consol Application(控制台应用程序)。
(2)掌握WINDOWS API的使用方法。
(3)编写测试程序,理解用户态运行和核心态运行。
2、程序清单清单1-1 一个简单的Windows控制台应用程序// hello项目# include <iostream>void main(){std::cout << “Hello, Win32 Consol Application” << std :: endl ;}清单1-2 核心态运行和用户态运行时间比计算// proclist项目# include <windows.h># include <tlhelp32.h># include <iostream.h>// 当在用户模式机内核模式下都提供所耗时间时,在内核模式下进行所耗时间的64位计算的帮助方法DWORD GetKernelModePercentage(const FILETIME& ftKernel,const FILETIME& ftUser){// 将FILETIME结构转化为64位整数ULONGLONG qwKernel=(((ULONGLONG)ftKernel.dwHighDateTime)<<32)+ftKernel.dwLowDateTime;ULONGLONG qwUser=(((ULONGLONG)ftUser.dwHighDateTime)<<32)+ftUser.dwLowDateTime;// 将消耗时间相加,然后计算消耗在内核模式下的时间百分比ULONGLONG qwTotal=qwKernel+qwUser;DWORD dwPct=(DWORD)(((ULONGLONG)100*qwKernel)/qwTotal);return(dwPct);}// 以下是将当前运行过程名和消耗在内核模式下的时间百分数都显示出来的应用程序void main(int argc,char *argv[]){if(argc<2){cout<<"请给出你要查询的程序名"<<endl;exit(0);}// 对当前系统中运行的过程拍取“快照”HANDLE hSnapshot=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,// 提取当前过程0);// 如果是当前过程,就将其忽略// 初始化过程入口PROCESSENTRY32 pe;::ZeroMemory(&pe,sizeof(pe));pe.dwSize=sizeof(pe);BOOL bMore=::Process32First(hSnapshot,&pe);BOOL found = FALSE;while(bMore){// 打开用于读取的过程if(!strcmp(pe.szExeFile,argv[1])){found = TRUE;HANDLE hProcess=::OpenProcess(PROCESS_QUERY_INFORMA TION,// 指明要得到信息FALSE,// 不必继承这一句柄pe.th32ProcessID);// 要打开的进程if (hProcess!=NULL){// 找出进程的时间FILETIME ftCreation,ftKernelMode,ftUserMode,ftExit;::GetProcessTimes(hProcess,// 所感兴趣的进程&ftCreation,// 进程的启动时间&ftExit,// 结束时间(如果有的话)&ftKernelMode,// 在内核模式下消耗的时间&ftUserMode);// 在用户模式下消耗的时间// 计算内核模式消耗的时间百分比DWORD dwPctKernel=::GetKernelModePercentage(ftKernelMode,// 在内核模式上消耗的时间ftUserMode);// 在用户模式下消耗的时间// 向用户显示进程的某些信息cout<< "process ID: " << pe.th32ProcessID<< ",EXE file:" << pe.szExeFile<< ",%d in Kernel mode: " << dwPctKernel << endl;// 消除句柄::CloseHandle(hProcess);}}// 转向下一个进程bMore=::Process32Next(hSnapshot,&pe);}if(found==FALSE){cout<<"当前系统没有这个可执行程序正在运行"<<endl;exit(0);}}清单1-3 核心态运行和用户态运行时间测试程序#include <stdio.h>main(){int i,j;while(1){for(i=0;i<1000;i++);for(j=1;j<1000;j++) printf(“enter kernel mode running.”);}}实验二进程管理1、实验目的1) 通过创建进程、观察正在运行的进程和终止进程的程序设计和调试操作,进一步熟悉操作系统的进程概念,理解Windows进程的“一生”。
生产者消费者问题实验报告

操作系统课程设计实验报告实验名称: 生产者消费者问题姓名/学号:一、实验目的以生产者和消费者问题为例, 学习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.大致由三个模块组成:i.主程序(main):ii.创建信号量、共享内存并进行初始化iii.创建生产者、消费者进程, 生产者执行pro_fun(), 消费者执行con_fun()iv.等待所有子进程的结束v.删除信号量、共享内存i.生产者进程(pro_fun):ii.通过key获得信号量、共享内存的ID, 将内存添加到自己的地址空间iii.P(empty), P(mutex), Add(data), V(mutex), V(full)iv.解除和共享内存的关联i.消费者进程(con_fun):ii.通过key获得信号量、共享内存的ID, 将内存添加到自己的地址空间iii.P(full), P(mutex), Add(data), V(mutex), V(empty)iv.解除和共享内存的关联循环队列部分:加入数据: 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函数的参数区分主进程和生产者、消费者进程。
(完整word版)生产者-消费者问题

课程设计报告课程名:操作系统专业学生姓名班级学号指导教师完成日期博雅学院“操作系统”课程设计报告-—生产者—消费者问题的模拟实现1.课程设计的目的本课程设计是学习完“操作系统原理”课程后进行的一次全面的综合训练,通过课程设计,更好地掌握操作系统的原理及实现方法,加深对操作系统基础理论和重要算法的理解,加强学生的动手能力。
2.设计内容2.1 概述用多进程同步方法解决生产者-消费者问题,C或C++语言实现。
通过研究Linux 的进程机制和信号量实现生产者消费者问题的并发控制。
说明:有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1-20这20个整型数.设计要求:(1)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容,当前指针位置和生产者/消费者县城的标识符。
(2)生产者和消费者各有两个以上。
(3)多个生产者或多个消费者之间须有共享对缓冲区进行操作的函数代码。
2.2 设计原理多进程是一种非常简洁的多任务操作方式。
在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种烦琐的多任务工作方式。
生产者-消费者方案是多进程应用程序开发中最常用的构造之一。
因此困难也在于此。
因为在一个应用程序中可以多次重复生产者—消费者行为,其代码也可以如此。
设计中创建了Consumer 类,该类通过在一些多进程应用程序中促进代码重用以及简化代码调试和维护来解决这个问题。
多进程应用程序通常利用生产者—消费者编程方案,其中由生产者进程创建重复性作业,将其传递给作业队列,然后由消费者进程处理作业.多进程是一种使应用程序能同时处理多个操作的编程技术。
通常有两种不同类型的多进程操作使用多个进程:适时事件,当作业必须在特定的时间或在特定的间隔内调度执行时;后台处理,当后台事件必须与当前执行流并行处理或执行时;适时事件的示例包括程序提醒、超时事件以及诸如轮询和刷新之类的重复性操作。
生产者与消费者问题(附源码)

操作系统实验报告专业网络工程班级08102 学号姓名课程名称操作系统学年2010-2011 学期下课程类别专业必修■限选□任选□实践□实验时间2010年11月3日实验名称实验一:生产者与消费者问题实验目的和要求全面理解生产者与消费者问题模型,掌握解决该问题的算法思想,正确使用同步机制。
实验软硬件要求Pentium ||| 450以上CPU 64MB以上内存WINDOWS XPVisual C++6.0实验内容、方法和步骤(可附页)问题描述:一组生产者向一组消费者提供商品,共享一个有界缓冲池,生产者向其中放入商品,消费者从中取得商品。
假定这些生产者和消费者互相等效,只要缓冲池未满,生产者可将商品送入缓冲池;只要缓冲池未空,消费者可从缓冲池取走一商品。
功能要求:根据进程同步机制,编写一个解决上述问题的程序,可显示缓冲池状态、放商品、取商品等过程。
具体参数:3个生产者进程,2个消费者进程;缓冲区单元个数N=4;在本程序中是缓冲区中的数从0变为1表示模拟生产一个产品,消费时则将对应缓冲区内的1变为0,为模拟消费一个产品。
实验结果(可附页)见截图小结这次多线程的操作系统实验,使我对线程的概念以及多线程程序中线程间的运行有了更深的认识,同时也让我的编程能力得到了一定的提高。
这次做的用多线程实现生产者与消费者模型的实验,由于我的编程能力基础比较差,对线程也是一无所知,所以一开始觉得无从下手,但幸好老师给了充足的时间,我通过看网上找的视频资料以及请教同学才渐渐地有了一点概念,然后我试着从网上下了一些多线程的程序分析里面的语句,基本弄懂了多线程的原理。
评定成绩:批阅教师:年月日一、问题概述三个生产者向两个消费者提供消息,它们共享一个有界缓冲池,缓冲池有四个缓冲区,生产者向其中投放消息,消费者从中取得消息。
假定这些生产者和消费者互相等效,只要缓冲池未满,生产者可将消息送入缓冲池;只要缓冲池未空,消费者可从缓冲池取走一个消息。
生产者消费者pv例题

生产者消费者pv例题生产者消费者问题是一个经典的并发编程问题,主要涉及到多个线程之间的同步和通信。
这个问题可以分为两部分:生产者和消费者。
生产者负责生成一定量的数据放到缓冲区,而消费者则从缓冲区中取出数据。
为了防止缓冲区溢出和被耗尽,需要使用到信号量等机制来进行同步。
以下是一个简单的生产者消费者问题的例子,用到了PV操作来控制:```c#include <stdio.h>#include <pthread.h>#include <stdlib.h>#define BUFFER_SIZE 100int buffer[BUFFER_SIZE];int in = 0, out = 0;pthread_mutex_t mutex; //互斥锁pthread_cond_t cond_empty, cond_full; //条件变量,分别表示缓冲区空和缓冲区满void *producer(void *arg) {int item;while (1) {item = produce_item(); //生产数据pthread_mutex_lock(&mutex);while ((in + 1) % BUFFER_SIZE == out) { //缓冲区满,等待消费者消费pthread_cond_wait(&cond_empty, &mutex);}buffer[in] = item;in = (in + 1) % BUFFER_SIZE; //入队printf("Producer produced item: %d\n", item);pthread_cond_signal(&cond_full); //唤醒消费者线程,告诉缓冲区有新数据可消费pthread_mutex_unlock(&mutex);}}void *consumer(void *arg) {while (1) {pthread_mutex_lock(&mutex);while (in == out) { //缓冲区空,等待生产者生产数据pthread_cond_wait(&cond_full, &mutex);}int item = buffer[out];out = (out + 1) % BUFFER_SIZE; //出队printf("Consumer consumed item: %d\n", item);pthread_cond_signal(&cond_empty); //唤醒生产者线程,告诉缓冲区有空间可放新数据pthread_mutex_unlock(&mutex);}}```。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
VC++学习:用vc 实现生产者消费者问题
文章来源:CSDN 作者:windcao
很多情况下我们需要多个线程互相协助,来完成同一个任务。
但是线程很难从外部进行控制。
利用线程同步技术可以使线程彼此交互,从而避免了外部控制对与时间和资源的浪费。
在实际工作过程中我就遇到了类似的问题,需要对共享的缓冲区进行操作。
有插入的线程也有读取的线程,这使我忽然想到了生产者和消费者。
我从MSDN 找到csdn 使用了各式各样的搜索引擎,只找到了很有现的关于CSemaphore 的资料。
////////////////////////////////////
// 生产者消费者问题
////////////////////////////////////
生产者要不断将数据放入共享的缓冲,消费者要不断从缓冲取出数据。
消费者必须等生产者
取走数据后才能再放新数据(不覆盖数据),消费者必须等生产者放入新数据后才能去取(不重复)。
/////////////////////////////////////
// 使用信号量的方法
/////////////////////////////////////
当线程使用指定数量的共享资源时,首先调用信号量的lock 方法"我能用资源吗"。
当有的空闲 共享资源时(此时计数器值>0)线程继续执行并且减少计数器的数量告诉其他线程"我用了××个资 源"。
否则挂起自己直到有足够的可用的资源为止。
当使用完资源时线程调用unlock 方法告诉其他 线程"我已经不用该资源了"。
/////////////////////////////////////
// 实现
////////////////////////////////////
///////////////////////////////////
1创建一个基于对话框的程序。
添加如下成员。
//////////////////////////////////
bool m_bSlow;//缓慢显示线程进行的结果
CProducerThread *m_pProducerThread;//生产者线程
CConsumerThread *m_pConsumerThread;//消费者线程
CSemaphore* m_pSemaphoreEmpty;//缓冲空的标志
CSemaphore* m_pSemaphoreFull;//缓冲满的标志
CMutex *m_pMutex;//互斥信号量
添加两编辑框用类向导,相关的添加成员
CString m_sBufCSM;//用来显示消费者取到的数据
CString m_sBuf;//显示生产者插入缓冲的数据
/////////////////////////////////////////////
2创建用户界面线程,生产者和消费者线程。
//////////////////////////////////////////// CProducerThread::CProducerThread(void* hParent) :m_pParentDlg(hParent)
{
}
int CProducerThread::Run()
{
CP_CDlg *pDlg;
pDlg=(CP_CDlg*)m_pParentDlg;
CSingleLock mutexLock(pDlg->m_pMutex);
for(int i=0;i<MAX_DATA_COUNT;I++){
pDlg->m_pSemaphoreEmpty->Lock(); mutexLock.Lock();
pDlg->m_sBuf.Format("%0.10d",i);
mutexLock.Unlock();
pDlg->m_pSemaphoreFull->Unlock();
}
return CWinThread::Run();
}
CConsumerThread::CConsumerThread(void *pParent) :m_pParent(pParent)
{
}
int CConsumerThread::Run()
{
CP_CDlg *pDlg;
pDlg=(CP_CDlg*)this->m_pParent;
char*pBuf;
pBuf=this->m_Data;
bool bSleep;
for(int i=0;i<MAX_DATA_COUNT;I+=10) {
pDlg->m_pSemaphoreFull->Lock();
pDlg->m_pMutex->Lock();
sprintf(pBuf,pDlg->m_sBuf);
bSleep=pDlg->m_bSlow ;
pDlg->m_pMutex->Unlock();
pBuf+=10;
if(pBuf>m_Data+CS M_BUF_COUNT-10)
pBuf=m_Data;
m_Data[CSM_BUF_COUNT]=0;
pDlg->m_pMutex->Lock();
sprintf(pDlg->m_sBufCSM.GetBuffer(CSM_BUF_COUNT+10),m_Data);
pDlg->m_pMutex->Unlock();
if (bSleep)
Sleep(100);
pDlg->m_pSemaphoreEmpty ->Unlock();
}
return CWinThread::Run();
}
///////////////////////////////////////
3启动线程:
///////////////////////////////////////
m_pSemaphoreFull =new CSemaphore(1,1);
m_pSemaphoreEmpty =new CSemaphore(0,1);
m_pMutex =new CMutex;
this->m_bUpdateAuto =false;
this->m_pProducerThread =new CProducerThread(this);
this->m_pConsumerThread =new CConsumerThread(this);
this->m_sBuf.Format("1234567890");
this->UpdateData(false);
this->m_pProducerThread->CreateThread(CREATE_SUSPENDED);
VERIFY(m_pProducerThread->SetThreadPriority(THREAD_PRIORITY_IDLE)); this->m_pConsumerThread->CreateThread(CREATE_SUSPENDED);
VERIFY(m_pConsumerThread->SetThreadPriority(THREAD_PRIORITY_IDLE)); this->m_pProducerThread->ResumeThread();
this->m_pConsumerThread->ResumeThread();。