收藏 分享(赏)

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

上传人:精品资料 文档编号:10654749 上传时间:2019-12-15 格式:DOC 页数:17 大小:151.01KB
下载 相关 举报
燕山大学操作系统课程设计说明书.doc_第1页
第1页 / 共17页
燕山大学操作系统课程设计说明书.doc_第2页
第2页 / 共17页
燕山大学操作系统课程设计说明书.doc_第3页
第3页 / 共17页
燕山大学操作系统课程设计说明书.doc_第4页
第4页 / 共17页
燕山大学操作系统课程设计说明书.doc_第5页
第5页 / 共17页
点击查看更多>>
资源描述

1、 燕山大学课程设计说明书课程设计名称:操作系统题目:多道程序缓冲区协调操作 (模拟生产者消费者问题) 课题负责人: 学院: 信息科学与工程学院 班级: 姓名: 学号: 课题开发日期:2014 年 1 月 13 日 自评成绩: A 目录1 概述-31.1 目的-31.2 主要完成的任务-31.3 使用的开发工具、开发语言-31.4 本软件解决的主要问题 -42 设计的基本理念、概念和原理-42.1 设计的基本理念-42.2 基本概念-42.3 基本原理-53 总体设计-53.1 基本的技术路线:面向对象-53.2 模块关系及总体流程-54 详细设计-74.1 变量设计-74.2 线程的设计-74

2、.3 button 按钮的设计-85 编码设计-95.1 开发环境-95.2 注意事项-95.3 主要代码设计-9PUTTER 线程的设计-9MOVER1 线程的设计-10GETTER1 线程的设计-11“开始”按钮的设计-12“结束”按钮的设计-145.4 解决的主要难题-166 测试出现的问题及其解决方案-167 工程总结-168 参考文献-16多道程序缓冲区协调操作演示程序设计说明书1 概述1.1 目的计算机操作系统是计算机系统中最不可缺少的,最常用的软件,也是核心的,最接近于计算机硬件的软件。其特点是内容繁多,概念抽象,因此造成理解困难,掌握不易。本软件的主要目的是通过直观的演示,使学

3、生能够感性的明白掌握多道程序及其进程同步和互斥的程序设计的基本方法。1.2 主要完成的任务(1)可随机产生字符数据,由生产者的 put 操作不断将生产的字符数据放入容器 1(Buffer1)中。(2)通过搬运者的 Move1 操作要不断地将容器 1(Buffer1)的数据取到容器2(Buffer2)中。(3)通过搬运者的 Move2 操作要不断地将容器 1(Buffer1)的数据取到容器3(Buffer3)中。(4)通过消费者 1 的 GET 操作不断的从容器 2(buffer2)中取出数据(5)通过消费者 2 的 GET 操作不断地从容器 3(Buffer3)中取出数据。(6)生产者,搬运者

4、,消费者的数目,buffer 容量可自己设定,但数目不宜过多;默认为生产者 5,消费者 1 为 5,消费者 2 为 5,Move1 为 2,Move2 为2,buffer1 容量为 10,buffer2 容量为 10,buffer3 容量为 10。(7) PUT、 Move1、Move2、 GET1,GET2 每次操作一个数据,在操作的过程中数据不丢失,每个 Buffer 每次只能接受一个 PUT 或一个 Move 或一个 Get,多个操作不能同时操作同一 BUFFER。(8)能够实时显示 Buffer 的操作过程,以及每个 Buffer 的当前放入的数据,每个 buffer 中的数据的个数。

5、(9)能够对生产者,搬运者,消费者的速度进行自由控制。(10) 当程序运行开始后,计时器就开始计时,直到运行结束,显示运行的总时间。(11) 运行结束后,能够汇总总运行时时间、已生产产品数、消费者 1 已消费产品数、消费者 2 已消费的产品数、总消费的产品数。1.3 使用的开发工具、开发语言开发工具:VS2010开发语言:C+C+是面向对象的一种编程语言,窗口程序设计中 MFC 已经将 windows 最底层的 API 函数以类的形式封装好,使用方便。 其特点有:1.面向对象;2.平台无关性;3.安全性;4.健壮性;1.4 本软件解决的主要问题对 Buffer 操作的多线程同步问题,利用操作系

6、统的 P、V 原语操作和 C+语言的 Thread 线程对 put、move、get 等多线程进行协调处理,实现了多线程并发执行的原理。用程序演示了操作系统中经典的生产者和消费者问题。2 设计的基本理念、概念和原理2.1 设计的基本理念使用 VS2010 创建了一个基本对话框类,并在对话框中添加了基本需要的所有控件:(1) buffer1,buffer2,buffer3 三个 LISTBOX 控件,用于显示各个 buffer 中的当前内容。(2) 添加了 3 个编辑框控件,分别用于对 3 个容器(buffer)容量的控制。(3) 添加 1 个编辑框控件用于输入数值确定线程执行速度。(4) 添加

7、 5 个编辑框控件,用于对生产者,移动物流,消费者数量的控制。五个线程用于对 buffer 容器的控制(PUTTER,MOVER1,MOVER2,GETTER1,GETTER2):(1) PUTTER 线程产生随机字符,并放入 buffer1 中,实现生产者的生产过程。(2) MOVER1,MOVER2 线程分别将 buffer1 中的数据移动至 buffer2 和 buffer3 中。(3) GETTER1,GETTER2 线程分别将 buffer2 和 buffer3 中的数据字符移出,实现消费者的消费过程。多个变量分别统计需要显示的数据:(1) 三个变量分别统计 buffer1,buff

8、er2,buffer3 中的数据并实时显示出来。(2) 五个变量进行数据汇总,显示最后的运行总时间,生产者生产数量,消费者消费数量 。通过 MFC 的对话框中按钮实现对所有线程的控制:(1) “开始”按钮:开始所有线程,实现多线程程序同步。(2) “结束”按钮:结束所有线程,并显示数据汇总情况。2.2基本概念面向对象,进程,线程,线程的同步,线程的互斥,多道程序。2.3 基本原理经典的生产者与消费者同步原理,通过互斥体和互斥信号来实现线程的等待,线程间的同步问题,线程之间的协调的问题。3.总体设计3.1 基本的技术路线:面向对象运用面向对象的设计理念,设计所要求的PUTTER,MOVER1,M

9、OVER2,GETTER1,GETTER2 五个线程,达到信号量的控制,变量的值确定,实现 BUFFER 一次只能操作一个动作,实现线程的同步,阻塞以及他们之间的协调问题。3.2 模块关系及总体流程Pca 对话框类:主界面设计、显示数据、过程演示PUTTER 线程:生产者:执行 put 操作MOVER1 线程:搬运者 1:执行 move1 操作GETTER1 线程:消费者 1:执行 get 操作MOVER2 线程:搬运者 2:执行 move2 操作GETTER2 线程:消费者 2:执行 get 操作图 1. 模块关系图 2.总体流程参数设定(或使用默认数据)开始运行(速度控制)结束动态显示每个

10、 buffer中的字符数据内容,移动过程以及数量数据汇总显示退出4.详细设计4.1 变量设计g_hMutex1,g_hMutex2,g_hMutex3:三个互斥体,分别控制一次只能对buffer实现一次操作。g_hFullItems1,g_hFullItems2,g_hFullItems3g_hEmptyItems1,g_hEmptyItems2,g_hEmptyItems3: 六个信号量,分别控制buffer中是否有空闲空间以及是否有数据可供移动,并进行互斥操作。clock_t类型的 start,finish变量,通过调用clock()函数得到线程运行的总时间。struct PThreadi

11、nt ptid;CpacDlg * dlg; 定义线程的结构体,用于线程通过结构体参数调用窗口类,从而实现线程对窗口的控制。SIZE_1 , SIZE_2 , SIZE_3:编辑框控件添加的变量,从而实现动态对容器buffer容量的控制。SPEED:控件添加的变量,实现对线程速度的控制。Produce_Num ,Consumer1_Num ,Consumer2_Num ,Move1_Num ,Move2_Num:控件添加的变量,实现对生产者,消费者,物流移动数量的控制。Con1_Num ,Pro_Num ,Con2_Num ,Con_Num:控件添加的变量,实现最终的数据统计汇总显示。Buff

12、er1,buffer2,buffer3:ListBox控件添加的控制变量,用于显示各个buffer中的字符数据内容。4.2 线程的设计PUTTER 线程产生随机字符,并放入 buffer1 中,实现生产者的生产过程。 DWORD WINAPI PUTTER(LPVOID para) /PUT线程其参数为 LPVOID para ,在创建线程时通过P_hThreadsi =CreateThread(NULL,0,PUTTER,(LPVOID) 语句,第四个参数传递了结构体参数,将当前对话框窗口类指针传递给线程函数,通过PThread * pthread = (PThread *)para;/规范

13、化参数CpacDlg * dlg = pthread-dlg;语句来实现对当前对话框窗口中所有参数的调用。MOVER1,MOVER2,GETTER1,GETTER2线程与PUTTER线程类似。4.3 button 按钮的设计“开始”按钮: 创建每个互斥体,互斥信号以及线程。void CpacDlg:OnBnClickedButton1()/ TODO: 在此添加控件通知处理程序代码UpdateData(1);g_hMutex1 = :CreateMutex(NULL,FALSE,NULL); /buff1互斥锁g_hFullItems1 = :CreateSemaphore(NULL,0,SI

14、ZE_1,NULL); /buff1信号量g_hEmptyItems1 = :CreateSemaphore(NULL,SIZE_1,SIZE_1,NULL);。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。 。/创建PUT线程for (int i=0;idlg;int i = pthread-ptid;int j=dlg-SPEED;int speed = 1000*j;LARGE_INTEGER nFrequency;/设置随机数的种子if(:QueryPerformanceFrequency( :QueryPerformanceC

15、ounter(:srand(unsigned)nStartCounter.LowPart); else / 否则使用当前系统时间初始化随机种子(毫秒级):srand(unsigned)time(NULL);while(true)CString buf;WaitForSingleObject(g_hEmptyItems1,INFINITE); /进行P操作WaitForSingleObject(g_hMutex1,INFINITE);/产生随机字符(A-Z)char ch;ch = char ( (rand() % 26) + 65 );buf.Format(_T(“put%c“),ch);dl

16、g-buffer1.InsertString(0,buf);dlg-Pro_Num+; /确定生产总数量int buf1c; /确定当前buffer1中的产品数量CString str;buf1c = dlg-buffer1.GetCount();str.Format(_T(“%d个“),buf1c);dlg-Buffer_C.SetWindowTextW(str); /在窗口中显示当前buffer1的数据数量:Sleep(speed); /速度设置ReleaseMutex(g_hMutex1); /进行V操作ReleaseSemaphore(g_hFullItems1,1,NULL);ret

17、urn 0;MOVER1线程的设计:DWORD WINAPI MOVER1(LPVOID para) /MOVE1线程PThread * pthread = (PThread *) para; /规范化参数CpacDlg * dlg = pthread-dlg;int i = pthread-ptid;int j=(dlg-SPEED);int speed =1000*j;while(true)WaitForSingleObject(g_hFullItems1,INFINITE); /进行P操作WaitForSingleObject(g_hEmptyItems2,INFINITE);WaitF

18、orSingleObject(g_hMutex1,INFINITE);WaitForSingleObject(g_hMutex2,INFINITE);/将buffer1中的数据移至buffer2中CString cs;int n;n = dlg-buffer1.GetCount();dlg-buffer1.GetText(n-1,cs);dlg-buffer1.DeleteString(n-1);CString cc;cc.Format(_T(“move1-“);cs = cc + cs;dlg-buffer2.InsertString(0,cs);int buf1c; /确定当前buffer

19、1中的产品数量CString str;buf1c = dlg-buffer1.GetCount();str.Format(_T(“%d个“),buf1c);dlg-Buffer_C.SetWindowTextW(str); /显示当前buffer1中的产品数量int buf2c; /确定当前buffer2中的产品数量CString str1;buf2c = dlg-buffer2.GetCount();str1.Format(_T(“%d个“),buf2c);dlg-Buf_C1.SetWindowTextW(str1); /显示当前buffer2中的产品数量:Sleep(speed); /设

20、置速度ReleaseMutex(g_hMutex2); /进行V操作ReleaseMutex(g_hMutex1);ReleaseSemaphore(g_hFullItems2,1,NULL);ReleaseSemaphore(g_hEmptyItems1,1,NULL);return 0;GETTER1 线程的设计:DWORD WINAPI GETTER1(LPVOID para) /GET1线程PThread * pthread = (PThread *)para;/规范化参数CpacDlg * dlg = pthread-dlg;int i = pthread-ptid;int j=(d

21、lg-SPEED);int speed =1000*j ;while(true)WaitForSingleObject(g_hFullItems2,INFINITE); /进行P操作WaitForSingleObject(g_hMutex2,INFINITE);/移出buffer2中的数据CString cs;int n;n = dlg-buffer2.GetCount();dlg-buffer2.GetText(n-1,cs);dlg-buffer2.DeleteString(n-1);dlg-Con1_Num = dlg-Con1_Num + 1; /消费者1消费的产品数量加1int bu

22、f2c; /确定当前buffer2中的产品数量CString str1;buf2c = dlg-buffer2.GetCount();str1.Format(_T(“%d个“),buf2c);dlg-Buf_C1.SetWindowTextW(str1);:Sleep(speed); /设置速度ReleaseMutex(g_hMutex2); /进行V操作ReleaseSemaphore(g_hEmptyItems2,1,NULL);return 0;“开始”按钮的设计:void CpacDlg:OnBnClickedButton1()/ TODO: 在此添加控件通知处理程序代码UpdateD

23、ata(1);g_hMutex1 = :CreateMutex(NULL,FALSE,NULL); /buff1互斥锁g_hFullItems1 = :CreateSemaphore(NULL,0,SIZE_1,NULL); /buff1信号量g_hEmptyItems1 = :CreateSemaphore(NULL,SIZE_1,SIZE_1,NULL);g_hMutex2 = :CreateMutex(NULL,FALSE,NULL);g_hFullItems2 = :CreateSemaphore(NULL,0,SIZE_2,NULL); /buff2互斥锁g_hEmptyItems2

24、 = :CreateSemaphore(NULL,SIZE_2,SIZE_2,NULL);g_hMutex3 = :CreateMutex(NULL,FALSE,NULL);g_hFullItems3 = :CreateSemaphore(NULL,0,SIZE_3,NULL); /buff3互斥锁g_hEmptyItems3 = :CreateSemaphore(NULL,SIZE_3,SIZE_3,NULL);start = clock(); /获得线程开始时间/创建PUT线程for (int i=0;iProduce_Num;+i)pthread0.dlg = this;pthread0

25、.ptid = i;P_hThreadsi=CreateThread(NULL,0,PUTTER,(LPVOID)/if(P_hThreadsi = NULL) MessageBox(TEXT(“线程创建错误!“);/创建MOVE1和MOVE2线程for(int j=0;jMove1_Num;+j)pthread1.dlg = this;pthread1.ptid = j;M1_hThreadsj=CreateThread(NULL,0,MOVER1,(LPVOID)if(M1_hThreadsj = NULL) MessageBox(TEXT(“线程创建错误!“);for(int k=0;k

26、Move2_Num;+k)pthread2.dlg = this;pthread2.ptid = k;M2_hThreadsk=CreateThread(NULL,0,MOVER2,(LPVOID)if(M2_hThreadsk = NULL) MessageBox(TEXT(“线程创建错误!“);/创建GET1和GET2线程for (int m=0;mConsumer1_Num;+m)pthread3.dlg = this;pthread3.ptid = m;C1_hThreadsm=CreateThread(NULL,0,GETTER1,(LPVOID)if(C1_hThreadsm =

27、NULL) MessageBox(TEXT(“线程创建错误!“);for (int n=0;nConsumer2_Num;+n)pthread4.dlg = this;pthread4.ptid = n;C2_hThreadsn=CreateThread(NULL,0,GETTER2,(LPVOID)if(C2_hThreadsn = NULL) MessageBox(TEXT(“线程创建错误!“);“结束”按钮的设计:void CpacDlg:OnBnClickedButton2() / TODO: 在此添加控件通知处理程序代码/UpdateData(1);DWORD KP_Thread10

28、;for(int i=0;iProduce_Num;i+)/GetExitCodeThread(P_hThreadsi,TerminateThread(P_hThreadsi,KP_Threadi); /结束线程/ExitThread(KP_Threadi);DWORD KM1_Thread1;for(int i=0;iMove1_Num;i+)/GetExitCodeThread(M1_hThreadsi,TerminateThread(M1_hThreadsi,KM1_Threadi);/ExitThread(KM1_Threadi);DWORD KM2_Thread1;for(int i

29、=0;iMove2_Num;i+)/GetExitCodeThread(M2_hThreadsi,TerminateThread(M2_hThreadsi,KM2_Threadi);/ExitThread(KM2_Threadi);DWORD KC1_Thread10;for(int i=0;iConsumer1_Num;i+)/GetExitCodeThread(C1_hThreadsi,TerminateThread(C1_hThreadsi,KC1_Threadi);DWORD KC2_Thread10;for(int i=0;iConsumer2_Num;i+)TerminateThr

30、ead(C1_hThreadsi,KC2_Threadi);double duration;finish = clock(); /得到线程结束时间duration = double (finish - start)/ CLOCKS_PER_SEC); /得到线程运行总时间CString str4;str4.Format(_T(“%2.4f秒“),duration);CLOCK.SetWindowTextW(str4); /输出线程运行总时间CString str;str.Format(_T(“%d个“),Pro_Num);Pro_NUM.SetWindowTextW(str); /输出生产者最

31、终生产总数CString str1;str1.Format(_T(“%d个“),Con1_Num);Con1_NUM.SetWindowTextW(str1); /输出消费者1消费产品总数CString str2;str2.Format(_T(“%d个“),Con2_Num);Con2_NUM.SetWindowTextW(str2); /输出消费者2消费产品总数CString str3;Con_Num = Con1_Num + Con2_Num;str3.Format(_T(“%d个“),Con_Num);Con_NUM.SetWindowTextW(str3); /输出总消费产品数量5.4

32、 解决的主要难题(1) 生产搬运消费的过程显示;(2) 多线程之间的同步、互斥问题;(3) Buffer 的数据的安全问题;(4) 程序运行时间显示问题(5) 对各个线程放入取出速度的任意控制问题;6 测试出现的问题及其解决方案(1) 测试过程中出现了多个 Put、Move 或 get 不能互斥的访问 Buffer,通过查阅书籍反复测试,经老师、助教老师指点,适当的设置线程 sleep()时间基本解决。 (2) 初始设计时,界面设计感到很不满意,经多次改进,添加元素,当然,由于时间原因,只达到了初步满意程度,还有待进一步改进。(3) 设计过程中出现了地址访问错误,经过老师指点,不断调试,添加了

33、变量,使得地址错误得到解决。7 工程总结通过操作系统课程设计这一小项目的实践,使得我获得很多的收获,弥补了自己的不足。使我对操作系统中多线程并发有了更深的理解,我再次体会到计算机专业要注重理论基础的学习,更要重视实践环节,特别是向操作系统这种要求实践能力编程能力很强的科目。今后在掌握理论的同时,我会更加注重提高自己的思考、设计、编写程序的能力。要懂得去查阅资料,获得了与项目相关的知识,并快速应用到自己的程序编写中。对于编程,我体会到有一点是很重要的,那就是拿到一个程序要求后首先要构想它的整体框架,然后想好每部分怎么实现,并且在编写代码时要注意编程习惯、编程风格,要有良好的可读性,所以注释部分也是很重要的。另外,在设计编写代码过程中,我逐渐改变了原来看到报很多错连看也不愿看的习惯,逐渐体会到耐心调试是一个非常好的变成习惯,不要怕报错,而是要勇于一步步地查找错误,修改错误。在今后的学习和编程中,我会逐渐的去改变不良习惯,将以上注意点付诸实践。8.参考文献【1】汤小丹,汤子瀛等.计算机操作系统.西安电子科技大学出版社.2009【2】Stephen Prata著.C+ Primer Plus.人民邮电大学出版社.2013

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报