多道程序缓冲区协调操作操作系统设计.docx
- 文档编号:26134612
- 上传时间:2023-06-17
- 格式:DOCX
- 页数:31
- 大小:131.90KB
多道程序缓冲区协调操作操作系统设计.docx
《多道程序缓冲区协调操作操作系统设计.docx》由会员分享,可在线阅读,更多相关《多道程序缓冲区协调操作操作系统设计.docx(31页珍藏版)》请在冰豆网上搜索。
多道程序缓冲区协调操作操作系统设计
多道程序缓冲区协调操作
1.概述
在程序中使用多线程时,一般很少有多个线程能在其生命期内进行完全独立的操作。
更多的情况是一些线程进行某些处理操作,而其它的线程必须对其处理结果进行了解。
正常情况下对这种处理结果的了解应当在其处理任务完成后进行。
如果不采取适当的措施,其它线程往往会在线程处理任务结束前就去访问处理结果,这就很有可能得到有关处理结果的错误的了解。
例如,多个线程同时访问同一个全局变量,如果都是读取操作,则不会出现问题。
如果一个线程负责改变此变量的值,而其他线程负责同时读取变量内容,则不能保证读取到的数据是经过写线程修改后的。
为了确保读线程读取到的是经过修改的变量,就必须在向变量写入数据时禁止其他线程对其的任何访问,直至赋值过程结束后再解除对其他线程的访问限制。
像这种保证线程能了解其他线程任务处理结束后的处理结果而采取的保护措施即为线程同步。
1.1设计目的
(1)了解提出信号量的背景
(2)掌握信号量的基本概念及PV操作的原理
(3)进一步熟悉信号量解决的经典问题
(4)利用信号量的原理实现不同操作系统下同步互斥问题
1.2设计要求
(1)可以随机产生字符数据,由put操作放入Buff1,buffer中容量单位是字符。
(2)提供良好图形界面,显示Buffer的操作过程。
(3)可以设定各Buffer的容量、PUT、GET、Move操作的个数;
(4)可以设定PUT、GET、Move操作的速度;
(5)实时显示每个Buffer中数据的个数和数据的内容,空闲Buffer的空间的个数;
(6)实时显示线程、进程所处于等待(阻塞)状态的个数
(7)程序运行结束,显示汇总数据:
总的运行时间;
Buffer中数据的个数;
已放入BUFFER的数据个数;
已取出的数据个数;
平均每个buffer中的数据个数。
1.3主要完成的任务
图1
对该模型(图1)实例化,利用图形界面直观易懂的特点,把完全抽象的线程的就绪、阻止、运行的概念以及同步互斥的过程用图形动态的显示出来。
1.4环境、工具
VC++6.0,WINDOW7
2使用的基本概念和原理
2.1基本概念
信号量:
为解决多进程线程同步与互斥问题,让两个或多个多道进程线程通过特殊的变量展开交互。
线程:
是进程的一个实体,是进程上下文中执行的代码序列,是被系统调度的基本单元。
进程:
进程是正在运行的程序实体,并且包括这个运行的程序中占据的所有系统资源。
互斥与同步:
进程的同步与互斥是指进程在推进时的相互制约关系。
进程同步:
它主要源于进程合作,是进程间共同完成一项任务时直接发生相互作用的关系。
进程互斥:
它主要源于资源共享,是进程之间的间接制约关系。
2.2基本原理
本程序使用信号量作为同步互斥的工具,当然也可以用其它的,通过对BUFFER1、BUFFER2、BUFFER3的容量,还有控制权设置不同的信号量来协调PUT、GET2、GET3、MOVE1、MOVE2线程,使其同步来实现P、V操作。
本程序并非真正的传输数据,只是对一个数据计数器加减来模拟数据的增加减少,被送来被取走,然后通过定时刷新,将线程的状态、数据显示到界面上。
3总体设计
3.1基本的技术路线
MFC中已实现有对线程操作和同步互斥的全部类,但是他对实现P、V操作的模拟不够直观;使用API面向过程的话,比较灵活,但程序的可读性、维护性较差。
我们使用二者的优点,取长补短,采用混合编程的方式对问题进行描述和演示。
3.2软件的总体结构、模块关系、总体流程
图1总体结构
设置设置
显示修改
图2模块关系
图3流程图
3.3线程规划
我们创建三类线程:
(1)PUT线程(往BUFFER1里放数据,相当于生产者)。
(2)MOVE1线程(从BUFFER1里取数据并放到BUFFER2里,相当于搬运者)。
MOVE2线程(从BUFFER1里取数据并放到BUFFER3里,相当于搬运者)。
(3)GET2线程(从BUFFER2里取数据,相当于消费者)。
GET3线程(从BUFFER3里取数据,相当于消费者)。
每类线程可由用户自行设定线程的个数。
4详细设计
4.1设计思想
设计了3个主要函数,分别为:
生产者函数put,消费者函数get2、get3,转移函数move1、move2,下面详细介绍各个类的功能。
Put函数用于实现通过执行P操作判断buffer1是否有空,buffer1是否可操作,并向buffer1中置数据,同时将表示buffer1中数据数buffer1number加+1,放入数据后执行V操作。
Move1函数通过执行P操作来判断buffer1中是否有数据,是否可操作,buffer2中是否有空间,是否可操作,将buffer1中的数据移至buffer2中,并使buffer1number--,buffer2number++,确定buffer中现有的数据总数。
之后再进行相应的V操作。
Move2函数通过执行P操作来判断buffer1中是否有数据,是否可操作,buffer3中是否有空间,是否可操作,将buffer1中的数据移至buffer3中,并使buffer1number--,buffer3number++,确定buffer中现有的数据总数。
之后再进行相应的V操作。
Get2函数用于实现通过执行P操作判断buffer2是否有数据,buffer2是否可操作,并从buffer2中取数据,同时将表示buffer2中数据数buffer2number--,放入数据后执行V操作。
Get3函数用于实现通过执行P操作判断buffer3是否有数据,buffer3是否可操作,并从buffer3中取数据,同时将表示buffer3中数据数buffer3number--,放入数据后执行V操作。
4.2设计原理
生产者—消费者问题是相互合作的进程关系的一种抽象,可以利用信号量机制来解决生产者—消费者问题,利用互斥信号量mutex实现进程对缓冲池的互斥使用。
对信号量的操作只能通过两个原子操作:
Wait(s)和Signal(s).Wait(s)是等待信号的操作,进行S=S-1操作;Signal(s)是发送信号的操作,进行S=S+1操作。
wait若s-1后仍大于或等于零,则进程继续执行;若s-1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转进程调度;若相加结果大于或等于零,则从该信号的等待队列中唤醒一等待进程,然后再返回原进程继续执行或转进程调度
4.3信号量的设置
需要设置九个信号量full1empty1buffer1full2empty2buffer2full3empty3buffer3。
各信号量含义及初值如下:
full1表示buffer1是否有数据,初值为0;
empty1表示buffer1是否有空间,初值为m;
buffer1表示buffer1是否可操作,初值为1;
full2表示buffer2是否有数据,初值为0;
empty2表示buffer2是否有空间,初值为n;
buffer2表示buffer2是否可操作,初值为1。
full3表示buffer2是否有数据,初值为0;
empty3表示buffer2是否有空间,初值为p;
buffer3表示buffer2是否可操作,初值为1。
4.4基本函数说明
(1)线程创建函数
HANDLECreateThread(
LPSECURITY_ATTRIBUTESlpThreadAttributes.//线程安全属性
DWORDdwStackSize,//线程堆栈的初始化大小,等于0时为系统默认的堆栈大小
PLTHREAD_START_ROUTINElpStartAddress,//线程函数
LPVOIDlpParameter,//线程参数
DWORDdwCreationFlags,//创建方式
LPDWORDlpThreadId//线程标识符
}
该函数创建一个线程,如果没有特殊需要除第三个参数外都可设为0,按系统的默认取值对待,主要是第三个参数,它是线程程序的入口,线程序入口的标准形式为
UINTFUNCTION(LPVOIDparam)
线程函数里可以传一个指针做为参数(param),该参数由创建线程函数(CreateThread)里的第四个参数确定。
(2)信号量创建函数
HANDLECreateSemaphore(
LPSECURITY_ATTRIBUTESlpSemaphoreAttributes,//安全属性指针
LONGlInitialCount,//初始计数
LONGlMaximumCount,//最大计数
LPCTSTRlpName//对象名指针
)
该函数创建一个信号量,llnitialCount是对信号量的初始值,iMaximunCount为信号量的最大值,即信号量在一个范围内有效,例empty=:
:
CreateSemaphore(0,0,M,0);
第二个0为empty信号量的初始值,M为信号量的最大值,在这个范围内(0,M)信号量都是有信号的。
(3)信号量释放函数
BOOLReleaseSemaphore(
HANDLEhSemaphore,//信号量句柄
LONGlReleaseCount,//计数递增数量
LPLONGlpPreviousCount//先前计数
)
该函数为释放信号量,因为信号量为系统资源,数目有限,所以使用完毕后,最后将资源释放。
(4)等待函数
DWORDWaitForSingleObjec(
HANDLEhHandle,//对象句柄
DWORDdwMilliseconds//等待的时间,单位为毫秒
)
5.编码设计
5.1开发环境的设置和建立
打开VC++,点击文件—>新建—>项目,弹出新建项目对话框,选择MFC—>MFC应用程序,为我们的项目起一个名字,点击确定。
我们选择基于对话框的MFC应用程序,单击完成,项目创建完成。
如下图。
5.2程序界面
5.3主要的程序代码
//homeworkDlg.cpp:
implementationfile
//
#include"stdafx.h"
#include"homework.h"
#include"homeworkDlg.h"
#ifdef_DEBUG
#definenewDEBUG_NEW
#undefTHIS_FILE
staticcharTHIS_FILE[]=__FILE__;
#endif
//#defineDELAY1000
#definep(s):
:
WaitForSingleObject(s,INFINITE)
#definev(s):
:
ReleaseSemaphore(s,1,NULL)
/////////////////////////////////////////////////////////////////////////////
//CAboutDlgdialogusedforAppAbout
voidDrawArrow(CRectrc,CDC*pDC,COLORREFcol);
voidDrawBuffer(intx,intnumber,CDC*pDC);
classCAboutDlg:
publicCDialog
{
public:
CAboutDlg();
//DialogData
//{{AFX_DATA(CAboutDlg)
enum{IDD=IDD_ABOUTBOX};
//}}AFX_DATA
//ClassWizardgeneratedvirtualfunctionoverrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtualvoidDoDataExchange(CDataExchange*pDX);//DDX/DDVsupport
//}}AFX_VIRTUAL
//Implementation
protected:
//{{AFX_MSG(CAboutDlg)
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg:
:
CAboutDlg():
CDialog(CAboutDlg:
:
IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
voidCAboutDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg,CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
//Nomessagehandlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CHomeworkDlgdialog
CHomeworkDlg:
:
CHomeworkDlg(CWnd*pParent/*=NULL*/)
:
CDialog(CHomeworkDlg:
:
IDD,pParent)
{
//{{AFX_DATA_INIT(CHomeworkDlg)
m_put=0;
DELAY=0;
M=0;
N=0;
m_move1=0;
m_get2=0;
m_get3=0;
m_move2=0;
P=0;
//}}AFX_DATA_INIT
//NotethatLoadIcondoesnotrequireasubsequentDestroyIconinWin32
m_hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
voidCHomeworkDlg:
:
DoDataExchange(CDataExchange*pDX)
{
CDialog:
:
DoDataExchange(pDX);
//{{AFX_DATA_MAP(CHomeworkDlg)
DDX_Control(pDX,IDC_SPIN9,m_sbbuffer3);
DDX_Control(pDX,IDC_SPIN8,m_sbMove2);
DDX_Control(pDX,IDC_SPIN7,m_sbGet3);
DDX_Control(pDX,IDC_SPIN3,m_sbGet2);
DDX_Control(pDX,IDC_SPIN2,m_sbMove1);
DDX_Control(pDX,IDC_SPIN6,m_sbbuffer2);
DDX_Control(pDX,IDC_SPIN5,m_sbbuffer1);
DDX_Control(pDX,IDC_SPIN4,m_delay);
DDX_Control(pDX,IDC_SPIN1,m_sbPut);
DDX_Text(pDX,IDC_EDIT1,m_put);
DDV_MinMaxInt(pDX,m_put,1,15);
DDX_Text(pDX,IDC_EDIT4,DELAY);
DDV_MinMaxInt(pDX,DELAY,300,1000);
DDX_Text(pDX,IDC_EDIT5,M);
DDV_MinMaxInt(pDX,M,1,20);
DDX_Text(pDX,IDC_EDIT6,N);
DDV_MinMaxInt(pDX,N,1,20);
DDX_Text(pDX,IDC_EDIT2,m_move1);
DDV_MinMaxInt(pDX,m_move1,1,15);
DDX_Text(pDX,IDC_EDIT3,m_get2);
DDV_MinMaxInt(pDX,m_get2,1,10);
DDX_Text(pDX,IDC_EDIT7,m_get3);
DDV_MinMaxInt(pDX,m_get3,1,10);
DDX_Text(pDX,IDC_EDIT8,m_move2);
DDV_MinMaxInt(pDX,m_move2,1,15);
DDX_Text(pDX,IDC_EDIT9,P);
DDV_MinMaxInt(pDX,P,1,20);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CHomeworkDlg,CDialog)
//{{AFX_MSG_MAP(CHomeworkDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON1,OnButton1)
ON_BN_CLICKED(IDC_BUTTON2,OnButton2)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_BUTTON3,OnButton3)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//CHomeworkDlgmessagehandlers
BOOLCHomeworkDlg:
:
OnInitDialog()
{
CDialog:
:
OnInitDialog();
//Add"About..."menuitemtosystemmenu.
//IDM_ABOUTBOXmustbeinthesystemcommandrange.
ASSERT((IDM_ABOUTBOX&0xFFF0)==IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX<0xF000);
CMenu*pSysMenu=GetSystemMenu(FALSE);
if(pSysMenu!
=NULL)
{
CStringstrAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if(!
strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING,IDM_ABOUTBOX,strAboutMenu);
}
}
//Settheiconforthisdialog.Theframeworkdoesthisautomatically
//whentheapplication'smainwindowisnotadialog
SetIcon(m_hIcon,TRUE);//Setbigicon
SetIcon(m_hIcon,FALSE);//Setsmallicon
buffer1number=buffer2number=buffer3number=putid=get2id=get3id=move1id=move2id=0;
alltime=allnumber1=allnumber2=allnumber3=0;
bput=bget2=bget3=bkill=bmove1=bmove2=FALSE;
CWnd*pWnd=this->GetDlgItem(IDC_STATIC);
pWnd->GetWindowRect(&rcUpdate);
this->ScreenToClient(&rcUpdate);
m_put=m_get2=m_get3=m_move1=m_move2=1;
M=N=P=5;
DELAY=500;
this->UpdateData(FALSE);
m_sbGet2.SetRange(1,15);
m_sbGet3.SetRange(1,15);
m_sbMove1.SetRange(1,15);
m_sbMove2.SetRange(1,15);
m_sbPut.SetRange(1,15);
m_delay.SetRange(300,1000);
m_sbbuffer1.SetRange(1,20);
m_sbbuffer2.SetRange(1,20);
m_sbbuffer3.SetRange(1,20);
returnTRUE;//returnTRUEunlessyousetthefocustoacontrol
}
voidCHomeworkDlg:
:
OnSysCommand(UINTnID,LPARAMlParam)
{
if((nID&0xFFF0)==IDM_ABOUTBOX)
{
CAboutDlgdlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog:
:
OnSysCommand(nID,lParam);
}
}
//Ifyouaddaminimizebuttontoyourdialog,youwillneedthecodebelow
//todrawtheicon.ForMFCapplicationsusingthedocument/viewmodel,
//thisisautomaticallydoneforyoubytheframework.
voidCHomeworkDlg:
:
OnPaint()
{
if(IsIconic())
{
CPaintDCdc(this);//devicecontextforpainting
SendMessage(WM_ICONERASEBKGND,(WPARAM)dc.GetSafeHdc(),0);
//Centericoninclientrectangle
intcxIcon=GetSystemMetrics(SM_CXICON);
intcyIcon=GetSystemMetrics(SM_CYICON);
CRectre
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 多道 程序 缓冲区 协调 操作 操作系统 设计