燕山大学操作系统课程设计说明书

发布时间:   来源:文档文库   
字号:

课题负责人:_____________________学院:___信息科学与工程学院__________班级:
姓名:___________________________学号:____________________________课题开发日期:2014113自评成绩:
A




目录
1概述----------------------
1.1目的------------------------1.2主要完成的任务---------------1.3使用的开发工具、开发语言——1.4本软件解决的主要问题---------
---------------------------33
——3
-----------3---------4
-------------------------------4
2设计的基本理念、概念和原理
2.1设计的基本理念-----------------------------42.2基本概念-----------------------------------42.3基本原理-----------------------------------5
3总体设计------------------------------5
3.1基本的技术路线:面向对象-------------------------------------53.2模块关系及总体流程-----------------------------5
4详细设计------------------------------7
4.1变量设计-----------------------------------74.2线程的设计---------------------------------74.3button按钮的设计------------------------------8
5编码设计------------------------------9
5.1开发环境-----------------------------------95.2注意事项-----------------------------------95.3主要代码设计---------------------------------9
PUTTER程的设计----------------------------------9MOVER线程的设计----------------------------------10GETTER线程的设计---------------------------------11“开始”按钮的设计--------------------------------12“结束”按钮的设计--------------------------------14
5.4解决的主要难题-------------------------------16
6测试出现的问题及其解决方案------------------167工程总结---------------------------------------------------168参考文献---------------------------------------------------16

多道程序缓冲区协调操作演示程序设计说明书
1概述
1.1目的
计算机操作系统是计算机系统中最不可缺少的,最常用的软件,也是核心的,最接近于计算机硬件的软件。其特点是内容繁多,概念抽象,因此造成理解困难,握不易。本软件的主要目的是通过直观的演示,使学生能够感性的明白掌握多道程序及其进程同步和互斥的程序设计的基本方法。
1.2主要完成的任务
(1可随机产生字符数据,由生产者的put操作不断将生产的字符数据放入容器1(Buffer1中。
(2通过搬运者的Move1操作要不断地将容器1(Buffer1的数据取到容器2(Buffer2中。
(3通过搬运者的Move2操作要不断地将容器1(Buffer1的数据取到容器3(Buffer3中。
(4通过消费者1GET操作不断的从容器2(buffer2中取出数据(5通过消费者2GET操作不断地从容器3(Buffer3中取出数据。(6生产者,搬运者,消费者的数目,buffer容量可自己设定,但数目不宜多;默认为生产者5,消费者15,消费者25,Move12Move22,buffer1容量为10,buffer2容量为10,buffer3容量为10
(7PUTMove1Move2GET1,GET2每次操作一个数据,在操作的过程数据不丢失,每个Buffer每次只能接受一个PUT或一个Move或一个Get,多个操作不能同时操作同一BUFFER
(8能够实时显示Buffer的操作过程,以及每个Buffer的当前放入的数据,buffer中的数据的个数。
(9能够对生产者,搬运者,消费者的速度进行自由控制。
(10当程序运行开始后,计时器就开始计时,直到运行结束,显示运行的总间。
(11运行结束后,能够汇总总运行时时间、已生产产品数、消费者1已消费品数、消费者2已消费的产品数、总消费的产品数。
1.3使用的开发工具、开发语言

开发工具:VS2010开发语言:C++
C++是面向对象的一种编程语言,窗口程序设计中MFC已经将windows底层的API函数以类的形式封装好,使用方便。
其特点有:1.面向对象;
2.
平台无关性;3.安全性;4.健壮性;
1.4本软件解决的主要问题
Buffer操作的多线程同步问题,利用操作系统的PV原语操作和C++Thread线程对putmoveget等多线程进行协调处理,实现了多线程并发执行的原理。用程序演示了操作系统中经典的生产者和消费者问题。
2设计的基本理念、概念和原理
2.1设计的基本理念
使用VS2010创建了一个基本对话框类,并在对话框中添加了基本需要的所控件:
1buffer1,buffer2,buffer3三个LISTBOX空件,用于显示各个buffer
中的当前内容。
2添加了3个编辑框控件,分别用于对3个容器(buffer)容量的控
制。
3添加1个编辑框控件用于输入数值确定线程执行速度。
4添加5个编辑框控件,用于对生产者,移动物流,消费者数量的控
制。
五个线程用于对buffer容器的控制(PUTTERMOVER1MOVER2GETTERGETTER2
1PUTTER线程产生随机字符,并放入buffer1中,实现生产者的生产
过程。
2MOVER1MOVER线程分别将buffer1中的数据移动至buffer2
buffer3中。
3GETTER1GETTER线程分别将buffer2buffer3中的数据字
移出,实现消费者的消费过程。
多个变量分别统计需要显示的数据:
1三个变量分别统计buffer1buffer2buffer3中的数据并实

时显示出来。
2五个变量进行数据汇总,显示最后的运行总时间,生产者生产
数量,消费者消费数量。
通过MFC的对话框中按钮实现对所有线程的控制:
1“开始”按钮:开始所有线程,实现多线程程序同步。2“结束”按钮:结束所有线程,并显示数据汇总情况。
2.2基本概念
面向对象,进程,线程,线程的同步,线程的互斥,多道程序。
2.3基本原理
经典的生产者与消费者同步原理,通过互斥体和互斥信号来实现线程的等待,线程间的同步问题,线程之间的协调的问题。
3.体设计
3.1基本的技术路线:面向对象
运用面向对象的设计理念,设计所要求的PUTTERMOVER1
M0VER2,GETTER1GETTER2五个线程,达到信号量的控制,变量的值确定,BUFFER一次只能操作一个动作,实现线程的同步,阻塞以及他们之间的协调问题。
3.2模块关系及总体流程
PUTTER线程:



生产者:执行put操作





M0VER1线程:搬运者1:执行move1操作

Pea对话框
类:主界面设计、示数据、过程演

MOVER2线程:搬运者2:执行move2操作









GETTER1线程:消费者1执行get操作


GETTER2线程:

消费者2:执行get操作


1•模块关系
2.总体流程

4.细设计4.1变量设计
g_hMutex1,g_hMutex2,g_hMutex3:三个互斥体,分别控制一次只能对
buffer实现一次操作。
g_hFullltems1g_hFullltems2g_hFullltems3g_hEmptyltems1g_hEmptyltems2g_hEmptyltems3:六个信号量,分别控制buffer中是否有空闲空间以及是否有数据可供移动,并进行互斥操作。
clock_t类型的start,finish变量,通过调用clock(函数得到线程运行的总时间。
structPThread{
intptid;
CpacDlg*dlg;
};定义线程的结构体,用于线程通过结构体参数调用窗口类,从
而实现线程对窗口的控制。
SlZE_1,SIZE_2,SIZE_3:编辑框控件添加的变量,从而实现动态对容器buffer容量的控制。
SPEED:控件添加的变量,实现对线程速度的控制。Produce_Num,Consumer1_Num,Co
nsumer2_Num,Move1_Num,Move2_Num控件添加的变量,实现对生产者,消费者,物流移动数量的控制。
Con1_Num,Pro_Num,Con2_Num,Con_Num:控件添加的变量,实现最终的数据统计汇总显示。
Buffer1buffer2buffer3:ListBox控件添加的控制变量,用于显示各buffer中的字符数据内容。
4.2线程的设计
PUTTER线程产生随机字符,并放入buffer1中,实现生产者的生产过程。
DWORDWlNAPlPUTTER(LPVOIDpara
//PUT线程
其参数为LPVOlDpara,在创建线程时通过
P_hThreads[i]=CreateThread(NULL,0,PUTTER,(LPVOID&pthreadO,O,&putlD[i];
语句,第四个参数传递了结构体参数,将当前对话框窗口类指针传递给线程函数,通过

PThread*pthread=(PThread*para;CpacDlg*dlg=pthread->dlg;
//规范化参数


语句来实现对当前对话框窗口中所有参数的调用。
M0VER,1M0VER2GETTER1GETTERS程与PUTTE线程类似
4.3button按钮的设计
“开始”按钮:创建每个互斥体,互斥信号以及线程。
voidCpacDlg::OnBnClickedButton1({
//TODO:在此添加控件通知处理程序代码UpdateData;
g_hMutex1=::CreateMutex(NULL,FALSE,NULL;g_hFullltems1=::CreateSemaphore(NULL,0,SIZE_1,NULL;g_hEmptyltems1=::CreateSemaphore(NULL,SIZE_1,
SIZE_1,NULL;
buff1互斥锁buff1信号量
oooooooooooooo
//创建PU■线程
for(inti=O;i{
pthreadO.dlg=this;pthreadO.ptid=i;P_hThreads[i]
=CreateThread(NULL,O,PUTTER,(LPVOID&pthreadO,O,&putlD[i];
if(P_hThreads[i]==NULLMessageBox(TEXT(
}
ooooooooo
//////////////////
"线程创建错误!"
ooooooooo
}
“结束”按
{
结束每一个线程,并进行数据汇总显示到对话框
voidCpacDlg::OnBnClickedButton2(
//TODO:在此添加控件通知处理程序代码//UpdateData(1;DWORDKP_Thread[10];for(inti=0;i{
TerminateThread(P_hThreads[i],KP_Thread[i];

5编码设计5.1开发环境
Windows7,已安装了VS2O10由于本软件是用C++语言开发,所以跨平台能比较好。本程序使用的主要类、函数,都是自己的写的,用到windowsbuilder件,用于设计界面。
5.2注意事项
1.编写代码要有良好的格式,有良好的注释,此程序要特别注意2.注意变量的使用,防止地址引用错误的产生
5.3主要代码设计
PUTTER线程的设计:
DWORDWINAPIPUTTER(LPVOIDpara{
PThread*pthread=(PThread*para;//规范化参数CpacDIg*dlg=pthread->dlg;inti=pthread->ptid;intj=dIg->SPEED;intspeed=1000*j;
//PUT线程
LARGE_INTEGERnFrequency/设置随机数的种子if(::QueryPerformanceFrequency(&nFrequency{
//如果支持高性能精度计数器,则使用其初始化随机种子LARGE_INTEGERnStartCounter;
::QueryPerformanceCounter(&nStartCounter;::srand((}
else//否则使用当前系统时间初始化随机种子(毫秒级{
::srand((}
while(true{
unsignedtime(NULL;
unsignednStartCounter.LowPart;
(微秒级

CStringbuf;
WaitForSin
gleObject(g_hEmptyltems1,INFINITE;WaitForSingleObject(g_hMutex1,INFINITE;
//产生随机字符(A-Zcharch;
ch=char((rand(%26+65;
buf.Format(_T("put-->%c",ch;dlg->buffer1.InsertString(0,buf;dlg->Pro_Num++;

intbuflc;
数量CStringstr;
buflc=dlg->buffer1.GetCount(;str.Format(_T("%d",buf1c;dlg->Buffer_C.SetWindowTextW(str;
数量::Sleep(speed;
ReleaseMutex(g_hMutex1;
ReleaseSemaphore(g_hFullltems1,1,NULL;


}
return0;}MOVER线程的设计:
DWORDWINAPIMOVER1(LPVOIDpara{

PThread*pthread=(PThread*para;CpacDlg*dlg=pthread->dlg;inti=pthread->ptid;
intj=(dlg->SPEED;intspeed=1000*j;
while(true{
//进行P操作
//确定生产总数量
//确定当前bufferl中的产品//在窗口中显示当前bufferl的数据
//速度设置//进行V操作
//MOVE1线程
//规范化参数


WaitForSingleObject(g_hFullltems1,INFINITE;//进行P操作
WaitForSin
gleObject(g_hEmptyltems2,INFINITE;WaitForSingleObject(g_hMutex1,INFINITE;WaitForSingleObject(g_hMutex2,INFINITE;//buffer1中的数据移至buffer2CStringcs;intn;
n=dlg->buffer1.GetCount(;dlg->buffer1.GetText(n-1,cs;dlg->buffer1.DeleteString(n-1;CStringcc;
cc.Format(_T("move1--";cs=cc+cs;
dlg->buffer2.InsertStri
ng(0,cs;intbuf1c;//确定当前bufferl
CStringstr;
buf1c=dlg->buffer1.GetCount(;str.Format(_T("%c",buf1c;dlg->Buffer_C.SetWi//显示当前bufferl
ndowTextW(str;
//确定当前buffer2
intbuf2c;CStringstrl;
buf2c=dlg->buffer2.GetCount(;str1.Format(_T("%d",buf2c;//显示当前buffer2dlg->Buf_C1.SetWindowTextW(strl;::Sleep(speed;
//设置速度ReleaseMutex(g_hMutex2;//进行V操作
ReleaseMutex(g_hMutex1;
ReleaseSemaphore(g_hFullltems2,1,NULL;ReleaseSemaphore(g_hEmptyltems1,1,NULL;
}return0;
}
GETTER1线程的设计:
DWORDWINAPIGETTER1(LPVOIDpara//GET1线程
{
//规范化参数

PThread*pthread=(PThread*para;
CpacDlg*dlg=pthread->dlg;inti=pthread->ptid;
中的产品数量
中的产品数量
中的产品数量
中的产品数量


intj=(dlg->SPEED;intspeed=1000*j;while(true{
WaitForSingleObject(g_hFullltems2,INFINITE;WaitForSingleObject(g_hMutex2,INFINITE;
//进行P操作
//移岀buffer2中的数据CStringcs;intn;
n=dlg->buffer2.GetCount(;dlg->buffer2.GetText(n-1,cs;dlg->buffer2.DeleteString(n-1;dlg->Con1_Num=dlg->Con1_Num+1;

//消费者1消费的产品数量加1
intbuf2c;CStringstr1;
buf2c=dlg->buffer2.GetCount(;str1.Format(_T("%c",buf2c;dlg->Buf_C1.SetWi

//确定当前buffer2中的产品数量
ndowTextW(str1;
::Sleep(speed;
ReleaseMutex(g_hMutex2;
ReleaseSemaphore(g_hEmptyltems2,1,NULL;
//设置速度
//进行V操作
}return0;}
“开始”按钮的设计:
voidCpacDlg::OnBnClickedButton1({
//TODO:在此添加控件通知处理程序代码UpdateData;
g_hMutex1=::CreateMutex(NULL,FALSE,NULL;g_hFullltems1=::CreateSemaphore(NULL,0,SIZE_1,NULL;g_hEmptyltems1=::CreateSemaphore(NULL,SIZE_1,

buff1互斥锁buff1信号量

SIZE_1,NULL;
g_hMutex2=::CreateMutex(NULL,FALSE,NULL;g_hFullltems2=::CreateSemaphore(NULL,0,SIZE_2,NULL;g_hEmptyltems2=::CreateSemaphore(NULL,SIZE_2,
SIZE_2,NULL;
buff2互斥锁
g_hMutex3=::CreateMutex(NULL,FALSE,NULL;g_hFullltems3=::CreateSemaphore(NULL,0,SIZE_3,NULL;g_hEmptyltems3=::CreateSemaphore(NULL,SIZE_3,
SIZE_3,NULL;
buff3互斥锁

start=clock(;//创建PU■线程
//获得线程开始时间
for(inti=0;i{
pthreadO.dlg=this;pthreadO.ptid=i;
P_hThreads[i]
=CreateThread(NULL,0,PUTTER,(LPVOID&pthread0,0,&putlD[i];
if(P_hThreads[i]==NULLMessageBox(TEXT(
}
//////////////////"线程创建错误!"
//仓【JMOVEMOVE线程for(intj=0;j
pthread1.dlg=this;pthread1.ptid=j;
M1_hThreads[j]
=CreateThread(NULL,0,MOVER1,(LPVOID&pthread1,0,&move1ID[j];
if(M1_hThreads[j]==NULLMessageBox(TEXT("线程创建错误!";}for(intk=0;k
pthread2.dlg=this;pthread2.ptid=k;
M2_hThreads[k]
=CreateThread(NULL,0,MOVER2,(LPVOID&pthread2,0,&move2ID[k];
if(M2_hThreads[k]==NULLMessageBox(TEXT("线程创建错误!";//创建GETGET线程
for(intm=0;m
pthread3.dlg=this;pthread3.ptid=m;
C1_hThreads[m]=CreateThread(NULL,0,GETTER1,(LPVOID&pthread3,0,&get1ID[m];
if(C1_hThreads[m]==NULLMessageBox(TEXT("线程创建错误!";}

for(intn=0;n
pthread4.dlg=this;pthread4.ptid=n;
C2_hThreads[n]=CreateThread(NULL,0,GETTER2,(LPVOID&pthread4,0,&get2ID[n];
if(C2_hThreads[n]==NULLMessageBox(TEXT("线程创建错误!";
}
}
“结束”按钮的设计:
voidCpacDlg::OnBnClickedButton2({
//TODO:在此添加控件通知处理程序代码UpdateData(1;DWORDKP_Thread[10];for(inti=0;i{
GetExitCodeThread(P_hThreads[i],&KP_Thread[i];TerminateThread(P_hThreads[i],KP_Thread[i];ExitThread(KP_Thread[i];}
DWORDKM1_Thread[1];for(inti=0;i{
GetExitCodeThread(M1_hThreads[i],&KM1_Thread[i];
TerminateThread(M1_hThreads[i],KM1_Thread[i];ExitThread(KM1_Thread[i];}
DWORDKM2_Thread[1];for(inti=0;i{
GetExitCodeThread(M2_hThreads[i],&KM2_Thread[i];

//结束线程

TerminateThread(M2_hThreads[i],KM2_Thread[i];ExitThread(KM2_Thread[i];}
DWORDKC1_Thread[10];for(inti=0;i{
GetExitCodeThread(C1_hThreads[i],&KC1_Thread[i];TerminateThread(C1_hThreads[i],KC1_Thread[i];}
DWORDKC2_Thread[10];for(inti=0;i{
TerminateThread(C1_hThreads[i],KC2_Thread[i];}
doubleduration;finish=clock(;
duration=double((finish-start/CLOCKS_PER_SEC;CStringstr4;
str4.Format(_T("%2.4f",duration;CLOCK.SetWindowTextW(str4;
CStringstr;
str.Format(_T("%d",Pro_Num;Pro_NUM.SetWindowTextW(str;
CStringstr1;
str1.Format(_T("%d",Con1_Num;Con1_NUM.SetWindowTextW(str1;CStringstr2;
str2.Format(_T("%d",Con2_Num;Con2_NUM.SetWindowTextW(str2;CStringstr3;
Con_Num=Con1_Num+Con2_Num;str3.Format(_T("%d",Con_Num;Con_NUM.SetWindowTextW(str3;
//得到线程结束时间//得到线程运行总时间
//输出线程运行总时间
//输出生产者最终生产总数
//输出消费者1消费产品总数//输出消费者2消费产品总数//输出总消费产品数量
5.4解决的主要难题
(1生产搬运消费的过程显示;(2多线程之间的同步、互斥问题;(3Buffer的数据的安全问题;(4程序运行时间显示问题
(5对各个线程放入取出速度的任意控制问题;
6测试出现的问题及其解决方案
(1
测试过程中出现了多个PutMoveget不能互斥的访问Buffer,通过查阅书籍反复测试,经老师、助教老师指点,适当的设置线程
(2
sleep(时间基本解决。
初始设计时,界面设计感到很不满意,经多次改进,添加元素,当然,由于时间原因,只达到了初步满意程度,还有待进一步改进。
(3设计过程中出现了地址访问错误,经过老师指点,不断调试,添加了变量,使得地址错误得到解决。
7工程总结
通过操作系统课程设计这一小项目的实践,使得我获得很多的收获,弥补了自己的不足。使我对操作系统中多线程并发有了更深的理解,
我再次体会到计算机专业要注重理论基
础的学习,更要重视实践环节,特别是向操作系统这种要求实践能力编程能力很强的科目。今后在掌握理论的同时,我会更加注重提高自己的思考、
设计、编写程序的能力。要懂得去
查阅资料,获得了与项目相关的知识,并快速应用到自己的程序编写中。
对于编程,我体会到有一点是很重要的,那就是拿到一个程序要求后首先要构想它的整体框架,然后想好每部分怎么实现,并且在编写代码时要注意编程习惯、良好的可读性,所以注释部分也是很重要的。
另外,在设计编写代码过程中,我逐渐改变了原来看到报很多错连看也不愿看的习惯,逐渐体会到耐心调试是一个非常好的变成习惯,修改错误。
在今后的学习和编程中,我会逐渐的去改变不良习惯,将以上注意点付诸实践。
不要怕报错,而是要勇于一步步地查找错误,
编程风格,要有
8.参考文献
1】汤小丹,汤子瀛等《计算机操作系统》.西安电子科技大学出版社.20092StephenPrata.C++PrimerPlus.人民邮电大学出版社.2013

本文来源:https://www.2haoxitong.net/k/doc/6eb78735acf8941ea76e58fafab069dc5122472c.html

《燕山大学操作系统课程设计说明书.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式