缓冲池模拟与实现.docx
《缓冲池模拟与实现.docx》由会员分享,可在线阅读,更多相关《缓冲池模拟与实现.docx(16页珍藏版)》请在冰豆网上搜索。
缓冲池模拟与实现
长春理工大学大学学生实验报告书学生用表实验名称
缓冲池的模拟实现
课程名称操作系统课程号学院(系)软件学院专业软件工程班级
学生姓名学号实验地点实验日期
一、实验目的1掌握缓冲池的结构
2掌握缓冲池的使用方法
二、实验内容1、实现输入、计算、输出进程并发执行
2、实现getBuf和putBuf函数。
三、实验步骤1、整体设计包括三个线程的模拟设计三个队列的链表设计还有三个
队列的同步与互斥的设计等
2、由于本次实验没有需要太多的数据结构因此数据结构的设计就只有
三个缓冲队列的设计先构造一个空的缓冲队列该队列是一个实体即是一个
确定的有结点的链表它是模拟缓冲池的载体输入与输出队列在构造时只有它
的头尾指针而没有它的实体这是因为它可以从空缓冲区里获得例如当计
算线程要数据计算时便可从空队列里获取一个缓冲区作为输入缓冲使用再把
它挂载到输入队列的队尾中去
算法流程图
实验内容如下
//缓冲队列类型的定义
#defineEMQ0//空缓冲队列
#defineINQ1//输入缓冲队列
#defineOUTQ2//输出缓冲队列
constintbufferpoolsize=50;////缓冲池大小,默认设置为50个
//结束运行标志
shortintm_end;GDOU
-B-11-112
//缓冲结构体的定义
typedefstructBuffer
{
intBufNo;//缓冲区号
intbuf;//缓冲内容
Buffer*next;//缓冲指向下一个指针
}buffer;
//线程函数声明
DWORDWINAPIInputThreadFunc(LPVOIDlpPara);//输入线程函数
DWORDWINAPIOutputThreadFunc(LPVOIDlpPara);//输出线程函数
DWORDWINAPICalThreadFunc(LPVOIDlpPara);//计算线程函数
//加入与摘取队列函数声明
voidputBuf(inttype,buffer*buf);//挂载到队列尾
buffer*getBuf(inttype);//从队列头中摘取一个缓冲区
//构造缓冲池函数的声明
voidConstructBuffer();
//线程的句柄
HANDLEhInputT;//输入线程
HANDLEhOutputT;//输出线程
HANDLEhCalculateT;//计算线程
//线程的ID
DWORDInputTid;//输入线程
DWORDOutputTid;//输出线程
DWORDCalculateTid;//计算线程
//三个互斥量信号句柄
HANDLEhmutexEMQ;//空队列的互斥信号量
HANDLEhmutexOUTQ;//装满输出队列的互斥信号量
HANDLEhmutexINQ;//装满输入队列的互斥信号量
//三个同步信号量
HANDLEhsemINQ;
HANDLEhsemOUTQ;
HANDLEhsemEMQ;
#include"windows.h"#include"iostream"
#include"stdlib.h"
#include"time.h"
#include"Main1.h"
usingnamespacestd;
//三个缓冲队列头与尾指针
buffer*hemq,*hinq,*houtq;//队头指针
buffer*lemq,*linq,*loutq;//队尾指针
//主函数
intmain()
{
cout<m_end=1;//运行结束标志
ConstructBuffer();//构造缓冲池
//创建互斥对象
hmutexEMQ=CreateMutex(NULL,FALSE,NULL);
hmutexOUTQ=CreateMutex(NULL,FALSE,NULL);
hmutexINQ=CreateMutex(NULL,FALSE,NULL);
//创建信号量对象
hsemINQ=CreateSemaphore(NULL,0,bufferpoolsize,NULL);
hsemOUTQ=CreateSemaphore(NULL,0,bufferpoolsize,NULL);
hsemEMQ=CreateSemaphore(NULL,bufferpoolsize,bufferpoolsize,NULL);
//创建线程
hInputT=CreateThread(NULL,0,InputThreadFunc,NULL,0,&InputTid);
Sleep(10);
hCalculateT=CreateThread(NULL,0,CalThreadFunc,NULL,0,&CalculateTid);
Sleep(10);
hOutputT=CreateThread(NULL,0,OutputThreadFunc,NULL,0,&OutputTid);
//Sleep(10000);
//system("pause");
if(getchar())
{//按回车后终止程序运行
m_end=0;
cout<<"程序已经终止!
"<}
//等待三个线程的结束返回WaitForSingleObject(hInputT,INFINITE);
WaitForSingleObject(hCalculateT,INFINITE);
WaitForSingleObject(hOutputT,INFINITE);
//释放线程的资源
CloseHandle(hInputT);
CloseHandle(hCalculateT);
CloseHandle(hOutputT);
return0;
}
//输入线程函数的实现
DWORDWINAPIInputThreadFunc(LPVOIDlpPara)//输入线程函数
{
intnRandom;
buffer*getbuf;
srand(time(0));//保证每次运行时产生的随机数独立
while(m_end)
{
Sleep(100);
nRandom=rand()%100+1;//产生1到100的随机数
//同步与互斥的控制
WaitForSingleObject(hsemEMQ,INFINITE);
WaitForSingleObject(hmutexEMQ,INFINITE);
getbuf=getBuf(EMQ);//访问空队列
getbuf->buf=nRandom;
cout<<"输入线程从"<<"缓冲单元"<BufNo<<"---收容输入
--->"<<"data="<buf<ReleaseMutex(hmutexEMQ);//释放互斥对象信号
//控制访问输入队列的互斥量
WaitForSingleObject(hmutexINQ,INFINITE);
putBuf(INQ,getbuf);//将输入的缓冲区挂载到输入队列的队尾
ReleaseMutex(hmutexINQ);
ReleaseSemaphore(hsemINQ,1,NULL);
}
return0;
}
//输出线程函数的实现DWORDWINAPIOutputThreadFunc(LPVOIDlpPara)//输出线程函数
{
buffer*Outputbuf;//一个临时交换区
while(m_end)
{
Sleep(100);
////同步与互斥的控制
WaitForSingleObject(hsemOUTQ,INFINITE);
WaitForSingleObject(hmutexOUTQ,INFINITE);
Outputbuf=getBuf(OUTQ);//从输出队列中提取一个提取输出缓冲
区
cout<<"输出线程从"<<"缓冲单元"<BufNo<<"---提取输
出--->"<<"data="<buf<//Outputbuf->buf=-1;//提取完成后将该缓冲区回收
ReleaseMutex(hmutexOUTQ);
WaitForSingleObject(hmutexEMQ,INFINITE);
putBuf(EMQ,Outputbuf);//回收的把它挂载到空队列的队尾
ReleaseMutex(hmutexEMQ);
ReleaseSemaphore(hsemEMQ,1,NULL);
}
return0;
}
//计算线程函数的实现
DWORDWINAPICalThreadFunc(LPVOIDlpPara)//计算线程函数
{
buffer*Calbuf1=NULL;
buffer*Calbuf2=NULL;
intnCal;
while(m_end)
{
Sleep(10);//因为计算线程的速度远远快于输入与输出线程所以它的
休眠时间应很小
////同步与互斥的控制
WaitForSingleObject(hsemINQ,INFINITE);
WaitForSingleObject(hmutexINQ,INFINITE);
Calbuf1=getBuf(INQ);//从输入队列中提取一个收容输入缓冲区
nCal=Calbuf1->buf;//提取数据
cout<<"计算线程从"<<"缓冲单元"<BufNo<<"---提取输入
--->"<<"data="<buf<//Calbuf->buf=-1;//系统将收回此缓冲区表示该缓冲区已空
ReleaseMutex(hmutexINQ);
WaitForSingleObject(hmutexEMQ,INFINITE);
putBuf(EMQ,Calbuf1);
ReleaseMutex(hmutexEMQ);
ReleaseSemaphore(hsemEMQ,1,NULL);
nCal=nCal+10000;//模拟输入数据的处理
WaitForSingleObject(hsemEMQ,INFINITE);
WaitForSingleObject(hmutexEMQ,INFINITE);
Calbuf2=getBuf(EMQ);//得到一个空的缓冲区作为收容输出
Calbuf2->buf=nCal;//存入运算结果
cout<<"计算线程从"<<"缓冲单元"<BufNo<<"---收容输出
--->"<<"data="<buf<ReleaseMutex(hmutexEMQ);
WaitForSingleObject(hmutexOUTQ,INFINITE);//把收容输出缓冲区挂
载到输出队列的队尾
putBuf(OUTQ,Calbuf2);
ReleaseMutex(hmutexOUTQ);
ReleaseSemaphore(hsemOUTQ,1,NULL);
}
return0;
}
//从队列中得到队头结点函数(实际相当于删除一个结点操作)
buffer*getBuf(inttype)
{
buffer*Returnbuf=NULL;
switch(type)
{
case0:
{
//判断该队列的缓冲个数是否还只有一个
if(hemq!
=lemq&&hemq->next->next!
=NULL)
{
Returnbuf=hemq->next;//取得队列头hemq->next=Returnbuf->next;//修正队列链表头指针的指
向
Returnbuf->next=NULL;
returnReturnbuf;
}
else
{
//假如该缓冲队列的个数只有一个的话则使得队头指针与队尾
指针相等级
//这样的话就可以防止队尾指针的丢失
Returnbuf=hemq->next;
hemq->next=Returnbuf->next;
Returnbuf->next=NULL;
lemq=hemq;
returnReturnbuf;
}
}break;
case1:
{
if(hinq!
=linq&&hinq->next->next!
=NULL)
{
Returnbuf=hinq->next;
hinq->next=Returnbuf->next;
Returnbuf->next=NULL;
returnReturnbuf;
}
else
{
Returnbuf=hinq->next;
hinq->next=Returnbuf->next;
Returnbuf->next=NULL;
linq=hinq;
returnReturnbuf;
}
}break;
case2:
{
if(houtq!
=loutq&&houtq->next->next!
=NULL)
{
Returnbuf=houtq->next;
houtq->next=Returnbuf->next;Returnbuf->next=NULL;
returnReturnbuf;
}
else
{
Returnbuf=houtq->next;
houtq->next=Returnbuf->next;
Returnbuf->next=NULL;
loutq=houtq;
returnReturnbuf;
}
}break;
}
}
//把某一类型的缓冲区挂载到队尾函数
//(实际相当于插入一个结点操作)
voidputBuf(inttype,buffer*buf)
{
switch(type)
{
case0:
{
if(buf!
=NULL)//该参数(buf)不为空的时候才执行因
为插入一个空的缓冲区是没有意义的
{
lemq->next=buf;//修正队列尾指针
lemq=buf;//队尾指针的跟踪
lemq->next=NULL;//队列尾指针赋空
}
}break;
case1:
{
if(buf!
=NULL)//同上
{
linq->next=buf;
linq=buf;
linq->next=NULL;
}
}break;
case2:
{
if(buf!
=NULL)
{loutq->next=buf;
loutq=buf;
loutq->next=NULL;
}
}break;
}
}
//构造缓冲池函数的声明
voidConstructBuffer()
{
buffer*p,*q;//为开辟动态缓冲区而设的两个变量
hemq=newbuffer;//创建空队列的头指针
hinq=newbuffer;//创建输入队列的头指针
houtq=newbuffer;//创建输出队列的头指针
q=hemq;
for(inti=0;i{
p=newbuffer;//开辟新的缓冲区
p->BufNo=i;//给开辟的缓冲区编号
p->buf=-1;
q->next=p;//前一缓冲区指向新的缓冲区
q=p;//q总是记住队尾的缓冲区
}
lemq=q;//空缓冲区队尾指针的确定
linq=hinq;//此时输入与输出队列的头指针与尾指针是一致的
loutq=houtq;
lemq->next=NULL;
linq->next=NULL;
loutq->next=NULL;
}
四、实验总结
成绩
指导教师日期注:
请用A4纸书写不够另附纸。