HUNAN UNIVERSITY
操作系统原理
实验报告
实 验 题 目 :
生产者-消费者问题
学 生 姓 名 :
学 生 学 号 :
靳清凯
20070810610
专 业 班 级 :
计算机科学与技术六班
同 组 成 员 :
蒋贵华 喻玲瑶
实 验 地 点 :
计通院实验中心
实 验 时 间 :
11.29
指 导 老 师 :
肖德贵、彭李翔
操 作 系 统 原 理 实 验 报 告
实习五 生产者-消费者问题实现
一、实验目的
1.熟悉临界资源、信号量及 PV 操作的定义与物理意义;
2.了解进程通信的方法;
3.掌握进程互斥与进程同步的相关知识;
4.掌握用信号量机制解决进程之间的同步与互斥问题;
5.实现生产者-消费者问题,深刻理解进程同步问题。
二、实验环境
VC++6.0
三、实验内容
经典同步问题:生产者—消费者,具体要求如下:
1.一个大小为 5 缓冲区,初始状态为空;
2.3 生产者,随机等待一段时间,往缓冲区中添加数据,若缓冲区已满,等待消费者取走数据
之后再添加,重复 5 次。
3.2 个消费者,随机等待一段时间,从缓冲区中读取数据,若缓冲区为空,等待生产者添加数
据之后再读取,重复 5 次。
Buffer(大小为 5)
生产者
………
消费者
模拟程序的程序流程图如下所示:
1.主程序流程图:
1
操 作 系 统 原 理 实 验 报 告
入口
初始化信号量
分配共享内存
创建生产者与消费者进程
释放内存
退出
2.生产者进程流程图:
2
操 作 系 统 原 理 实 验 报 告
3.消费者进程流程图:
四、实验结果(含程序、数据记录及分析、实验总结等)
实验设计方法:
1. 实验同步的设计方法:
实验中使用 WinAPI 函数创建了一个互斥量 h_Mutex,两个信号量 bufferFullSemaphore 用以录满的信
号, bufferEmptySemaphore 用以记录空的信号.
其中用到的函数方法:
h_Mutex = CreateMutex(NULL,false,NULL);
bufferFullSemaphore = CreateSemaphore(NULL,BUFFER_SIZE,BUFFER_SIZE,NULL);
bufferEmptySemaphore = CreateSemaphore(NULL,0,BUFFER_SIZE,NULL);
同时定义了:
3 个生产者入口函数为:
DWORD WINAPI Producter1(LPVOID pthread)
DWORD WINAPI Producter2(LPVOID pthread)
3
操 作 系 统 原 理 实 验 报 告
DWORD WINAPI Producter3(LPVOID pthread)
2 个消费者入口函数:
DWORD WINAPI Consumer1(LPVOID pthread)
DWORD WINAPI Consumer2(LPVOID pthread)
在每个入口函数中,使用函数:
DWORD WINAPI WaitForSingleObject(
__in
__in
HANDLE hHandle,
DWORD dwMilliseconds
);
BOOL WINAPI ReleaseSemaphore(
__in
__in
__out
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);
BOOL WINAPI ReleaseMutex(
__in
HANDLE hMutex
);
对互斥量以及相应的信号量进行管理,使线程能够同步运行.
然后在主函数中使用函数:
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes,
DWORD dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParamiter,
DWORD dwCreationFlags,
Lpdword lpThread
);
分别为每个生产者和消费者创建线程.
最后,使用函数
BOOL WINAPI TerminateThread(
__in_out
__in
HANDLE hThread,
DWORD dwExitCode
);
结束所有线程.
2. 实验数据的定义:
实验中定义了一个线程结构体,其中封装了 CListBox 类指针,即列表框的所有操作.
线程结构体定义如下:
typedef struct Threadinfo{
CListBox*pList;
}thread,*lpthread;
实验中使用的缓冲区定义为循环队列用以记录缓冲区中的消息内容,其定义如下:
const int BUFFER_SIZE =5;
CString buffer[BUFFER_SIZE] = {"0"};
int in = 0;
//用与追踪产品进缓冲区时的缓冲区数组下标
//缓冲区长度
//缓冲区循环队列
4
操 作 系 统 原 理 实 验 报 告
int out = 0;
实验中的消息定义统一为 CString 类.
3. 实验设计思想和设计流程
本程序是基于 MFC 对话框结构的应用程序.
设计思想:
实验调用 WinAPI 函数,创建多线程的同步方法,把列表框封装在新的结构体类作为入口函数传递参数
的指针,用以指定不同的列表框显示对应不同的内容.
设计流程:
如图:
<>
CMFCThreadDlg
DWORD WINAPI Producter1(LPVOID pthread)
DWORD WINAPI Producter1(LPVOID pthread)
DWORD WINAPI Producter1(LPVOID pthread)
DWORD WINAPI Consumer1(LPVOID pthread)
DWORD WINAPI Consumer1(LPVOID pthread)
buffer
int in,out;
thread thread1;
thread thread2;
HANDLE hThread1;
HANDLE hThread2;
HANDLE hThread3;
HANDLE hThread4;
HANDLE hThread5;
CListBoxm_ProList;
CListBoxm_ConList;
void OnCancle()
void OnClearUp()
void OnCreateThread()
void OnDestroyThread()
Threadinfo
CListBox*pList
由图 1 知,CMFCThfreadDlg 依赖 buffer,Threadinfo 和生产者与消费者的 5 个接口函数.
图 1
5
操 作 系 统 原 理 实 验 报 告
实验代码:
创建线程:
void CMFCThreadDlg::OnCreateThread()
{
// TODO: Add your control notification handler code here
GetDlgItem(IDC_DESTROY_THREAD)->EnableWindow(true);
DWORD code;
control=true;
DWORD ProducterID[3],ConsumerID[2];
thread1.pList=&m_ProList;
thread2.pList=&m_ConList;
h_Mutex = CreateMutex(NULL,false,NULL);
bufferFullSemaphore = CreateSemaphore(NULL,BUFFER_SIZE,BUFFER_SIZE,NULL);
bufferEmptySemaphore = CreateSemaphore(NULL,0,BUFFER_SIZE,NULL);
if(!GetExitCodeThread(hThread1,&code)||(code!=STILL_ACTIVE)){
6
操 作 系 统 原 理 实 验 报 告
hThread1=CreateThread(NULL,0,Producter1,&thread1,0,&ProducterID[0]);
}
if(!GetExitCodeThread(hThread2,&code)||(code!=STILL_ACTIVE)){
hThread2=CreateThread(NULL,0,Producter2,&thread1,0,&ProducterID[1]);
}
if(!GetExitCodeThread(hThread3,&code)||(code!=STILL_ACTIVE)){
hThread3=CreateThread(NULL,0,Producter3,&thread1,0,&ProducterID[2]);
}
if(!GetExitCodeThread(hThread4,&code)||(code!=STILL_ACTIVE)){
hThread4=CreateThread(NULL,0,Consumer1,&thread2,0,&ConsumerID[0]);
}
if(!GetExitCodeThread(hThread5,&code)||(code!=STILL_ACTIVE)){
hThread5=CreateThread(NULL,0,Consumer2,&thread2,0,&ConsumerID[1]);
}
}
结束线程:
void CMFCThreadDlg::OnDestroyThread()
{
// TODO: Add your control notification handler code here
DWORD code;
control=false;
if(GetExitCodeThread(hThread1,&code)&&(code==STILL_ACTIVE)){
TerminateThread(hThread1,0);
CloseHandle(hThread1);
}
if(GetExitCodeThread(hThread2,&code)&&(code==STILL_ACTIVE)){
TerminateThread(hThread2,0);
CloseHandle(hThread2);
}
if(GetExitCodeThread(hThread3,&code)&&(code==STILL_ACTIVE)){
7