操作系统-课程设计指导书.doc

上传人:asd****56 文档编号:70339423 上传时间:2023-01-19 格式:DOC 页数:72 大小:1.68MB
返回 下载 相关 举报
操作系统-课程设计指导书.doc_第1页
第1页 / 共72页
操作系统-课程设计指导书.doc_第2页
第2页 / 共72页
点击查看更多>>
资源描述

《操作系统-课程设计指导书.doc》由会员分享,可在线阅读,更多相关《操作系统-课程设计指导书.doc(72页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、操作系统课程设计指导书操作系统课程设计指导书1. 操作系统课程设计1.1 课程的性质和目的“操作系统基础”是计算机专业的核心专业课,“操作系统课程设计”是理解和巩固操作系统基本理论、原理和方法的重要的实践环节。 操作系统课程主要讲述的内容是多道操作系统的原理与技术,与其它计算机原理、编译原理、汇编语言、计算机网络、程序设计等专业课程关系十分密切。本课程设计的目的综合应用学生所学知识,建立系统和完整的计算机系统概念,理解和巩固操作系统基本理论、原理和方法,掌握多道程序设计基本技能。实验的目的:(1) 掌握进程和线程的概念;(2) 掌握进程控制原语或进程控制系统调用的使用;(3) 掌握多道程序设计

2、的基本理论、方法和技术;(4) 掌握相关语言进程控制的函数及win98或windows2000的进程控制的API函数和MFC的使用; (5) 培养学生多道程序设计的能力。1.2 课程的内容计算机操作系统是计算机系统中最不可缺少的、最常用的软件,也是核心的、最接近于计算机硬件的软件。计算机操作系统是计算机专业及其相关专业的主要的基础课程之一,其内容综合了各种操作系统的结构、设计思想、方法、技术和理论,其特点是内容繁多、概念抽象,因此造成理解困难、掌握不易。现代操作系统最为核心的概念是多道程序、进程和线程,它们对于操作系统的初学者掌握尤其不易。本课程设计的内容为“多道程序间的协同操作”,其指导思想

3、是通过这个课程设计掌握多道程序的基本要点,解决进程和线程概念的理解难点,以利用基本概念和原理的进行多道程序设计为重点,在有限的一周时间内,利用诸如VC+或Java掌握多道程序及其进程同步和互斥的设计的基本方法, 达到能用、会用、巧用的效果。1.3 学时分配和辅导 (1)基本任务简介、原理讲解 2学时 (2)软件设计 4学时 (3)上机编程、调试 24学时 (4)检查考核 2学时 每小班大约30人,每小班至少配备一名指导教师跟综辅导答疑,解决技术难题。要求指导教师熟悉多道程序间的协同操作、进程同步和互斥的原理,具有VC+或Java程序设计的经验。2课程设计的任务2.1 基本任务要求题目1:多道程

4、序缓冲区协调操作如下图所示,有10个PUT操作要不断循环地向Buffer1送数据,有一个Move操作要不断地将Buffer1的数据取到Buffer2,有20个GET操作要不断地从Buff2中取数据。BUFF1是10,BUFF2的容量是20, PUT、 MOVE、 GET每次操作一个数据,为了在操作的过程中要保证数据不丢失,每个Buffer每次只能接受一个PUT或一个Move或一个Get,多个操作不能同时操作同一BUFFER。设计一个多道程序完成上述操作。试用、原语协调PUT、 MOVE、GET的操作,并说明每个信号量的含义、初值和值的范围。Buffer2 Buffer1 PUT MOVE GE

5、T 图1 Buffer操作题目2:多道程序间协同操作(自拟) 学生自拟设计一个题目,可以是个游戏,可以解决一个简单的实际问题的解决,也可以是客观世界中事物处理的模拟,但要求能够反映多道程序间协同操作,采用多进程或多线程机制设计和运行,尽量体现进程间的同步和互斥关系。 2.2 开发环境、技术、工具和工期(1) 建议使用windowsXP、windows2000、Linux 或Unix操作系统,采用的编程语言为VC、VB、Java、Delphi、.NET或C+;(2) 采用多道程序设计技术实现;没有直接对thread and process 支持的语言,考虑使用API函数;(3) 一周之内完成。

6、2.3 基本功能要求(1) 显示Buffer的操作过程;(2) 可以确定Buffer的容量、PUT、GET、COPY操作的个数;(3) 自行确定放数据的速度,取数据的速度;(4) 实时显示每个Buffer中数据的个数,已放入Buffer的数据个数,已取的数据个数;(5) 程序运行结束,显示汇总数据:总的运行时间;Buffer中数据的个数;已放入BUFFER的数据个数;已放已取的数据个数;平均buffer中的数据个数。可以根据题目的基本要求进行丰富的创意和想象。2.4 运行要求(1) 经调试后程序能够正常运行,采用多进程或多线程方式运行,界面尽量体现多道程序的特点、进程间的同步和互斥关系。(2)

7、 本程序可运行在win98,XP、Win2000、Win2003、 Linux或Unix操作系统下,可安装到任意路径下。2.5 提交的材料(1) 提交软件安装盘;(2) 源程序;(3) 设计说明书(电子版):格式要求见4.10节描述;(4) 使用说明书(电子版):格式要求见4.10节描述。2.6评分和验收标准 2.6.1评分标准 (1) 软件演示及讲解 45分(2) 设计报告 35分(3) 使用手册 10分(4) 注释及良好的程序设计风格 10分2.6.2验收标准教师根据设计报告、软件的运行演示和学生回答问题的情况评定成绩。 (1)设计报告规范、完整,概念原理论述清楚、软件设计结构合理,独立完

8、成设计,软件运行正常,能够突出表现多道程序运行的特点,回答问题准确明了,可以评为优秀(A)。 (2)设计报告规范、完整,概念原理论述清楚、软件设计结构合理,独立完成、软件基本运行正常,能够表现多道程序运行的特点,回答问题正确,可以评为良(B)。 (3)设计报告规范、概念原理论述基本清楚、软件设计结构合理,基本独立完成,软件基本运行正常,基本能够表现多道程序运行的特点,回答问题部分正确,可以评为中良(C)。 (4)设计报告基本规范、概念原理论述基本清楚、软件设计结构基本合理,部分独立完成,软件基本可以运行,基本能够表现多道程序运行的特点,回答问题部分正确,可以评为及格(D)。 (5)设计报告不规

9、范、概念原理论述不清楚、软件设计结构不合理,大部分不能独立完成,软件基本不能运行,回答问题大部分不正确,可以评为不及格(E)。3设计的基本步骤(1) 需求分析查找相关技术资料,了解基本原理,根据题目要求创意软件的功能。.(2) 设计软件的界面程序运行界面要求使用中文或中英文对照.。(3) 总体设计 确定基本的技术路线:面向过程还是面向对象;确定软件的总体结构、模块关系、总体流程;确立要创立的进程或线程;确定开发要使用的语言环境;要解决的关键技术问题。(4) 详细设计确定要使用的进程操作的函数、原语、API,掌握它们的使用的参数和返回值。确定模块内部的流程和实现算法;确定要设计的过程、构件、类、

10、对象、函数和它们的参数。(5) 编码设计建立设计编程的环境;注意编程的风格的规范。(6) 实际数据运行测试 检查程序是否有错误; 检查界面是否美观; 检查操作是否方便; 检查提供的信息是否清晰; 检查性能是否稳定。4设计说明书内容要求4.1 概述 目的; 主要完成的任务; 使用的开发工具; 解决的主要问题。4.2 使用的基本概念和原理多道程序;进程;线程;同步和互斥的概念。4.3 总体设计 确定基本的技术路线:面向过程还是面向对象;确定软件的总体结构、模块关系、总体流程;确立要创立的进程或线程。4.4 详细设计确定要利用的进程操作的函数、原语、API,掌握它们的使用的参数和返回值,要给出具体的

11、名称和参数及其解释;确定模块内部的流程和实现算法;确定要设计的过程、构件、类、对象、函数和它们的参数,要给出具体的名称和参数及其解释。4.5 编码设计开发环境的设置和建立;程序设计时要注意的事项;关键构件/插件的特点和使用;主要程序的代码设计及注释;如果使用、原语协调PUT、 MOVE、GET的操作,说明每个信号量的含义、初值和值的范围;解决的技术难点、经常犯的错误。4.6 测试时出现过的问题及其解决方法4.7 总结 详细列出已经课程设计的完成情况; 未完成的部分;收获、经验、教训和感受等。4.8参考文献列出你所用的参考文献,包括Web上的资源。4.9 格式要求(1) 论文开本为A4,页边距为

12、设置:上下分别为3cm,左右分别为2.9cm和2.8cm;(2) 报告书标题用小2号黑体字,横向居中排放;(3) 1级标题用小3号黑体;(4) 2级标题用4号黑体;(5) 3级标题用小4号黑体;(6) 正文用5号宋体字,行间距为最小值18磅;(7) 各层次标题均不得置于页面的最后一行,即不允许“背题”;(8) 图下方要有图号和图名,表上方要有表号和表名;(9) 参考文献编写项目和顺序规定如下: 序号 作者.书名.出版地:出版者,出版年:引用部分起止页 序号 作者.文章名.学术刊物名,年,卷(期):引用部分起止页表1 层次代号及说明层次名称示例说明全文标题 XXXX名居中排,章序用阿拉伯数字1级

13、标题1 题序顶格书写,与标题间空一字,下面阐述内容另起一段 2级标题1.1 3级标题1.1.1 5 用户使用说明书5.1 基本功能5.2 需要运行的环境5.3 安装5.4 运行5.5 操作6 技术指导6.1 进程与线程进程是一个可执行的程序,由私有虚拟地址空间、代码、数据和其他操作系统资源进程组成。一个应用程序可以有一个或多个进程,一个进程可以有一个或多个线程,其中一个是主线程。动态性是进程最基本的特性。线程是操作系统分时调度分配CPU时间的基本实体,是进程的一个实体,是被系统独立调度和分派的基本单位,线程基本上不拥有自己的资源,只拥有一点点在运行中必不可少的资源(如程序计数器、一组寄存器和栈

14、),但它可与同属于一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程;同一进程中的多个线程之间可以并发执行。 由于创建新进程必须加载代码,而线程要执行的代码已经被映射到进程的地址空间,所以创建、执行线程的速度比进程更快。一个进程的所有线程共享进程的地址空间和全局变量,所以简化了线程之间的通讯。6.2 VC+相关函数6.2.1 Win32的进程与线程处理因为MFC没有提供类处理进程,所以直接使用了Win32 API函数。1. 进程的创建调用CreateProcess函数创建新的进程,运行指定的程序。CreateProcess的原型如下: BOOL CreateProce

15、ss( LPCTSTR lpApplicationName, LPTSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory, LPSTARTUPINFO lpStartupInfo, LPPROCESS_INFORMATION lpProcessInforma

16、tion);其中:lpApplicationName指向包含了要运行模块名字的字符串;lpCommandLine指向命令行字符串;lpProcessAttributes描述进程的安全性属性; lpThreadAttributes描述进程初始线程(主线程)的安全性属性;bInHeritHandles表示子进程(被创建的进程)是否可以继承父进程的句柄。可以继承的句柄有线程句柄、有名或无名管道、互斥对象、事件、信号量、映像文件、普通文件和通讯端口等;还有一些句柄不能被继承,如内存句柄、DLL实例句柄、GDI句柄、URER句柄等等。子进程继承的句柄由父进程通过命令行方式或者进程间通讯(IPC)方式由父

17、进程传递给它。dwCreationFlags表示创建进程的优先级类别和进程的类型。创建进程的类型分控制台进程、调试进程等;优先级类别用来控制进程的优先级别,分为Idle、Normal、High、Real_time四个类别。lpEnviroment指向环境变量块,环境变量可以被子进程继承。lpCurrentDirectory指向表示当前目录的字符串,当前目录可以继承。lpStartupInfo指向StartupInfo结构,控制进程的主窗口的出现方式。lpProcessInformation指向PROCESS_INFORMATION结构,用来存储返回的进程信息。从其参数可以看出创建一个新的进程需

18、要指定的信息。若进程创建成功的话,返回一个进程信息结构类型的指针。进程信息结构如下:typedef struct _PROCESS_INFORMATION HANDLE hProcess; HANDLE hThread; DWORD dwProcessId; DWORD dwThreadId; PROCESS_INFORMATION; 进程信息结构包括进程句柄,主线程句柄,进程ID,主线程ID。2. 进程的终止进程在以下情况下终止:(1) 调用ExitProcess结束进程;(2) 进程的主线程返回,隐含地调用ExitProcess导致进程结束;(3) 进程的最后一个线程终止;(4) 调用Te

19、rminateProcess终止进程;(5) 当要结束一个GDI进程时,发送WM_QUIT消息给主窗口,当然也可以从它的任一线程调用ExitProcess。3. 线程的创建 使用CreateThread函数创建线程,CreateThread的原型如下:HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThread

20、Id);其中:lpThreadAttributes表示创建线程的安全属性;dwStackSize指定线程栈的尺寸,如果为0则与进程主线程栈相同;lpStartAddress指定线程开始运行的地址;lpParameter表示传递给线程的32位的参数;dwCreateFlages表示是否创建后挂起线程(取值CREATE_SUSPEND),ResumeThread继续执行;lpThreadId用来存放返回的线程ID。4. 线程的优先级别 进程的每个优先级类包含了五个线程的优先级水平。在进程的优先级类确定之后,可以改变线程的优先级水平。用SetPriorityClass设置进程优先级类,用SetThr

21、eadPriority设置线程优先级水平。Normal级的线程可以被除了Idle级以外的任意线程抢占。5. 线程的终止 以下情况终止一个线程:(1) 调用了ExitThread函数; (2) 线程函数返回:主线程返回导致ExitProcess被调用,其它线程返回导致ExitThread被调用; (3) 调用ExitProcess导致进程的所有线程终止; (4) 调用TerminateThread终止一个线程; (5) 调用TerminateProcess终止一个进程时,导致其所有线程的终止。 当用TerminateProcess或者TerminateThread终止进程或线程时,DLL的入口函

22、数DllMain不会被执行(如果有DLL的话)。6. 线程局部存储 如果希望每个线程都可以有线程局部(Thread local)的静态存储数据,可以使用TLS线程局部存储技术。TLS为进程分配一个TLS索引,进程的每个线程通过这个索引存取自己的数据变量的拷贝。TLS对DLL是非常有用的。当一个新的进程使用DLL时,在DLL入口函数DllMain中使用TlsAlloc分配TLS索引,TLS索引就作为进程私有的全局变量被保存;当该进程的新的线程使用DLL时(Attahced to DLL),DllMain给它分配动态内存并且使用TlsSetValue把线程私有的数据按索引保存。DLL函数可以使用T

23、lsGetValue按索引读取调用线程的私有数据。TLS函数如下:l DWORD TlsAlloc() 在进程或DLL初始化时调用,并且把返回值(索引值)作为全局变量保存。l BOOL TlsSetValue( DWORD dwTlsIndex,LPVOID lpTlsValue);其中:dwTlsIndex是TlsAlloc分配的索引。lpTlsValue是线程在TLS槽中存放的数据指针,指针指向线程要保存的数据。线程首先分配动态内存并保存数据到此内存中,然后调用TlsSetValue保存内存指针到TLS槽。l LPVOID TlsGetValue( DWORD dwTlsIndex);其中

24、:dwTlsIndex是TlsAlloc分配的索引。当要存取保存的数据时,使用索引得到数据指针。l BOOL TlsFree( DWORD dwTlsIndex);其中:dwTlsIndex是TlsAlloc分配的索引。当每一个线程都不再使用局部存储数据时,线程释放它分配的动态内存。在TLS索引不再需要时,使用TlsFree释放索引。7. 线程同步 同步可以保证在一个时间内只有一个线程对某个资源(如操作系统资源等共享资源)有控制权。共享资源包括全局变量、公共数据成员或者句柄等。同步还可以使得有关联交互作用的代码按一定的顺序执行。 Win32提供了一组对象用来实现多线程的同步。这些对象有两种状态

25、:获得信号(Signaled)或者没有或则信号(Not signaled)。线程通过Win32 API提供的同步等待函数(Wait functions)来使用同步对象。一个同步对象在同步等待函数调用时被指定,调用同步函数地线程被阻塞(blocked),直到同步对象获得信号。被阻塞的线程不占用CPU时间。同步对象主要有:Critical_section(临界区),Event(事件),Mutex(互斥对象),Semaphores(信号量),下面着重解释怎么使用这些同步对象。l 临界区对象 定义一个临界区对象cs: CRITICAL_SECTION cs; 初始化该对象: InitializeCri

26、ticalSection(&cs);初始化时把对象设置为NOT_SINGALED,表示允许线程使用资源。 如果一段程序代码需要对某个资源进行同步保护,则这是一段临界区代码。在进入该临界区代码前调用EnterCriticalSection函数,这样,其他线程都不能执行该段代码,若它们试图执行就会被阻塞。完成临界区的执行之后,调用LeaveCriticalSection函数,其他的线程就可以继续执行该段代码。如果该函数不被调用,则其他线程将无限期的等待。l 事件对象 首先,调用CreateEvent函数创建一个事件对象,该函数返回一个事件句柄。然后,可以设置(SetEvent)或者复位(Reset

27、Event)一个事件对象,也可以发一个事件脉冲(PlusEvent),即设置一个事件对象,然后复位它。复位有两种形式:自动复位和人工复位。在创建事件对象时指定复位形式。 自动复位:当对象获得信号后,就释放下一个可用线程(优先级别最高的线程;如果优先级别相同,则等待队列中的第一个线程被释放)。 人工复位:当对象获得信号后,就释放所有可利用线程。 最后,使用CloseHandle销毁创建的事件对象。l 互斥对象 首先,调用CreateMutex创建互斥对象;然后,调用等待函数,可以的话利用关键资源;最后,调用RealseMutex释放互斥对象。 互斥对象可以在进程间使用,但临界区对象只能用于同一进

28、程的线程之间。l 信号量对象 在Win32中,信号量的数值变为0时给以信号。在有多个资源需要管理时可以使用信号量对象。 首先,调用CreateSemaphore创建一个信号量;然后,调用等待函数,如果允许的话,则利用关键资源;最后,调用RealeaseSemaphore释放信号量对象。 此外,还有其它句柄可以用来同步线程: 文件句柄(FILE HANDLES)命名管道句柄(NAMED PIPE HANDELS)控制台输入缓冲区句柄(CONSOLE INPUT BUFFER HANDLES)通讯设备句柄(COMMUNICTION DEVICE HANDLES)进程句柄(PROCESS HANDL

29、ES)线程句柄(THREAD HANDLES)例如,当一个进程或线程结束时,进程或线程句柄获得信号,等待该进程或者线程结束的线程被释放。8. 等待函数 Win32提供了一组等待函数用来让一个线程阻塞自己的执行,等待函数分三类。等待单个对象的(FOR SINGLE OBJECT)函数,包括: SignalObjectAndWait; WaitForSingleObject; WaitForSingleObjectEx。 函数参数包括同步对象的句柄和等待时间等。在以下情况下等待函数返回:同步对象获得信号时返回;等待时间达到了返回。如果等待时间不限制(Infinite),则只有同步对象获得信号才返回

30、;如果等待时间为0,则在测试了同步对象的状态之后马上返回。等待多个对象的(FOR MULTIPLE OBJECTS)的函数,包括: WaitForMultipleObjects; WaitForMultipleObjectsEx; MsgWaitForMultipleObjects; MsgWaitForMultipleObjectsEx。 函数参数包括同步对象的句柄,等待时间,是等待一个还是多个同步对象等等。 在以下情况下等待函数返回: 一个或全部同步对象获得信号时返回(在参数中指定是等待一个或多个同步对象);等待时间达到了返回:如果等待时间不限制(Infinite),则只有同步对象获得信号

31、才返回;如果等待时间为0,则在测试了同步对象的状态之后马上返回。可以发出提示的函数(ALTERABLE)函数,包括:MsgWaitForMultipleObjectsEx;SignalObjectAndWait;WaitForMultipleObjectsEx;WaitForSingleObjectEx;这些函数主要用于重叠(Overlapped)的I/O(异步I/O)。6.2.2 MFC的线程处理在Win32 API的基础之上,MFC提供了处理线程的类和函数。处理线程的类是CWinThread,函数是AfxBeginThread、AfxEndThread等。CWinThread是MFC线程类

32、,它的成员变量m_hThread和m_hThreadID是对应的Win32线程句柄和线程ID。 MFC明确区分两种线程:用户界面线程(User interface thread)和工作者线程(Worker thread)。用户界面线程一般用于处理用户输入并对用户产生的事件和消息作出应答。工作者线程用于完成不要求用户输入的任务,如耗时计算。 Win32 API并不区分线程类型,它只需要知道线程的开始地址以便它开始执行线程。MFC为用户界面线程特别地提供消息泵来处理用户界面的事件。CWinApp对象是用户界面线程对象的一个例子,CWinApp从类CWinThread派生并处理用户产生的事件和消息。

33、 1. 创建用户界面线程 通过以下步骤创建一个用户界面线程:(1) 从CWinThread派生一个有动态创建能力的类。使用DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏来支持动态创建; (2) 覆盖CWinThread的一些虚拟函数。其中:函数InitInstance是必须覆盖的,ExitInstance通常是要覆盖的; (3) 使用AfxBeginThread创建MFC线程对象和Win32线程对象。如果创建线程时没有指定CREATE_SUSPENDED,则开始执行线程; (4) 如果创建线程是指定了CREATE_SUSPENDED,则在适当的地方调用函数Resu

34、meThread开始执行线程。 2. 创建工作者线程 (1) 程序员不必从CWinThread派生新的线程类,只需要提供一个控制函数,由线程启动后执行该函数;(2) 使用AfxBeginThread创建MFC线程对象和Win32线程对象,如果创建线程时没有指定CREATE_SUSPENDED(创建后挂起),则创建的新线程开始执行;(3) 如果创建线程是指定了CREATE_SUSPENDED,则在适当的地方调用函数ResumeThread开始执行线程;(4) 虽然程序员没有从CWinThread派生类,但是MFC给工作者线程提供了缺省的CWinThread对象。3. AfxBeginThread

35、 用户界面线程和工作者线程都是由AfxBeginThread创建的。现在,考察该函数:MFC提供了两个重载版的AfxBeginThread,一个用于用户界面线程,另一个用于工作者线程,分别有如下的原型和过程。 用户界面线程的AfxBeginThread的原型如下: CWinThread* AFXAPI AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority, UINT nStackSize, DWORD dwCreateFlags, LPSECURITY_ATTRIBUTES lpSecurityAttrs); 其中: 参数1是从C

36、WinThread派生的RUNTIME_CLASS类; 参数2指定线程优先级,如果为0,则与创建该线程的线程相同; 参数3指定线程的堆栈大小,如果为0,则与创建该线程的线程相同; 参数4是一个创建标识,如果是CREATE_SUSPENDED,则在悬挂状态创建线程,在线程创建后线程挂起,否则线程在创建后开始线程的执行; 参数5表示线程的安全属性。工作者线程的AfxBeginThread的原型如下: CWinThread* AFXAPI AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority, UINT

37、nStackSize, DWORD dwCreateFlags, LPSECURITY_ATTRIBUTES lpSecurityAttrs)其中:参数1指定控制函数的地址;参数2指定传递给控制函数的参数;参数3、4、5分别指定线程的优先级、堆栈大小、创建标识、安全属性,含义同用户界面线程。 4. AfxBeginThread创建线程的流程 不论哪个AfxBeginThread,首先都是创建MFC线程对象,然后创建Win32线程对象。在创建MFC线程对象时,用户界面线程和工作者线程的创建分别调用了不同的构造函数。用户界面线程是从CWinThread派生的,所以,要先调用派生类的缺省构造函数,然

38、后调用CWinThread的缺省构造函数。 5. CreateThread和_AfxThreadEntry MFC使用CWinThread:CreateThread创建线程,不论对工作者线程或用户界面线程,都指定线程的入口函数是_AfxThreadEntry。_AfxThreadEntry调用AfxInitThread初始化线程。 CreateThread和_AfxThreadEntry在线程的创建过程中使用同步手段交互等待、执行。CreateThread由创建线程执行,_AfxThreadEntry由被创建的线程执行,两者通过两个事件对象(hEvent和hEvent2)同步。在创建了新线程之

39、后,创建线程将在hEvent事件上无限等待直到新线程给出创建结果;新线程在创建成功或者失败之后,触发事件hEvent让父线程运行,并且在hEven2上无限等待直到父线程退出CreateThread函数;父线程(创建线程)因为hEvent的置位结束等待,继续执行,退出CreateThread之前触发hEvent2事件;新线程(子线程)因为hEvent2的置位结束等待,开始执行控制函数(工作者线程)或者进入消息循环(用户界面线程)。 MFC在线程创建中使用了如下数据结构: struct _AFX_THREAD_STARTUP /传递给线程启动的参数(IN) _AFX_THREAD_STATE* p

40、ThreadState;/父线程的线程状态 CWinThread* pThread; /新创建的MFC线程对象 DWORD dwCreateFlags; /线程创建标识 _PNH pfnNewHandler; /新线程的句柄 HANDLE hEvent; /同步事件,线程创建成功或失败后置位 HANDLE hEvent2; /同步事件,新线程恢复执行后置位 /返回给创建线程的参数,在新线程恢复执行后赋值 BOOL bError; /如果创建发生错误,TRUE ; 该结构作为线程开始函数的参数被传递给_beginthreadex函数来创建和启动线程。_beginthreadex函数是“C”的线程

41、创建函数,具有如下原型: unsigned long _beginthreadex( void *security, unsigned stack_size, unsigned ( _stdcall *start_address )( void * ), void *arglist, unsigned initflag,unsigned *thrdaddr );6. 实现线程的消息循环 在MFC中,消息循环是由线程完成的。一般地,可以使用MFC缺省的消息循环(即使用函数CWindThrad:Run),但是,有些时候需要程序员自己实现一个线程的消息循环,比如在用户界面线程进行一个长时间计算处理或

42、者等待另一个线程时。一般有如下形式:while ( bDoingBackgroundProcessing) MSG msg;while ( :PeekMessage( &msg, NULL,0, 0, PM_NOREMOVE ) )if ( !PumpMessage( ) )bDoingBackgroundProcessing = FALSE; :PostQuitMessage( );break;LONG lIdle = 0;while ( AfxGetApp()-OnIdle(lIdle+ ) );程序员实现线程的消息循环有两个好处,一是顾及了MFC的Idle处理机制;二是在长时间的处理中可

43、以响应用户产生的事件或者消息。在同步对象上等待其它线程时,也可以使用同样的方式,只要把条件 bDoingBackgroundProcessing 换成如下形式:WaitForSingObject(hHandleOfEvent,0) = WAIT_TIMEOUT 即可。MFC处理线程和进程时还引入了一个重要的概念:状态,如线程状态(Thread State)、进程状态(Process State)、模块状态(Module State)等。6.3 多线程编程问题 在这部分将较为详细的讲解6.2中函数的应用及其遇到的问题。6.3.1 问题的提出编写一个耗时的单线程程序。新建一个基于对话框的应用程序S

44、ingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为IDC_SLEEP_SIX_SECOND,标题为“延时6秒”,添加按钮的响应函数,代码如下: void CSingleThreadDlg:OnSleepSixSecond() Sleep(6000); /延时6秒编译并运行应用程序,单击“延时6秒”按钮,你就会发现在这6秒期间程序就像“死机”一样,不再响应其它消息。这仅仅是一个小小的程序,如果在一个较大系统中多次出现这样的事件,势必会浪费很多计算机资源。为了更好地处理这种耗时的操作,我们有必要学习多线程编程。 6.3.2 Win32 API多线程编程例程1 MultiThread1建立一个基于对话框的工程MultiThread1,在对话框IDD_MULTITHREAD1_DIALOG中加入两个按钮和一个编辑框,两个按钮的ID分别是IDC_START,IDC_STOP ,标题分别为“启动”,“停止”,IDC_STOP的属性选中Disabled;编辑框的ID为IDC_TIME

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 技术资料 > 其他杂项

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com