Windows程序的执行单元课件

上传人:痛*** 文档编号:224359215 上传时间:2023-07-31 格式:PPT 页数:52 大小:136KB
收藏 版权申诉 举报 下载
Windows程序的执行单元课件_第1页
第1页 / 共52页
Windows程序的执行单元课件_第2页
第2页 / 共52页
Windows程序的执行单元课件_第3页
第3页 / 共52页
资源描述:

《Windows程序的执行单元课件》由会员分享,可在线阅读,更多相关《Windows程序的执行单元课件(52页珍藏版)》请在装配图网上搜索。

1、第3章Win32程序的执行单元第第3章章 Windows程序的执行单元程序的执行单元线程线程第3章Win32程序的执行单元3.1 多线程多线程线程的创建线程内核对象线程的终止线程的优先级C/C+运行期库第3章Win32程序的执行单元线程的创建线程的创建多线程并发执行,os为其轮流分配cpu时间片一般情况,主线程接受用户输入,显示运行结果;新创建的线程来处理长时间的操作,如读写文件、访问网络等,这样即便程序忙于繁重的工作也可以由专门的线程响应用户命令每个线程必须拥有入口点函数,主线程的为main。辅助线程入口点函数称为线程函数,定义如下:DWORDWINAPIThreadProc(LPVOIDl

2、pParam);函数名称ThreadProc可以是任意的第3章Win32程序的执行单元线程的创建线程的创建#defineWINAPI_stdcall;_stdcall是新标准c/c+调用方法,与标准c调用_cdecl相比,参数进栈次序相同,从右到左,但_stdcall采用自动清栈方式,而_cdecl采用手工清栈方式。由windows操作系统调用的函数(回调函数)必须声明为_stdcall没有显示说明的话,为_cdecl调用方式第3章Win32程序的执行单元线程的创建线程的创建创建新线程用CreateThreadHANDLECreateThread(LPSECURITY_ATTRIBUTESlp

3、sa,DWORDcbStack,LPTHREAD_START_ROUTINElpStartAddr,LPVOIDlpvThreadParam,DWORDfdwCreate,LPDWORDlpIDThread);第3章Win32程序的执行单元线程的创建线程的创建lpsainIgnored.MustbeNULL.指定线程安全属性cbStackin指定线程堆栈大小,NULL为默认大小lpStartAddrin线程函数起始地址lpvThreadParaminLongpointertoasingle32-bitparametervaluepassedtothethread.fdwCreateinSpec

4、ifiesflagsthatcontrolthecreationofthethread.0表示线程创建后立即运行lpIDThreadoutLongpointertoa32-bitvariablethatreceivesthethreadidentifier.IfthisparameterisNULL,thethreadidentifierisnotreturned.第3章Win32程序的执行单元WaitForSingleObjectDWORDWaitForSingleObject(HANDLEhHandle,DWORDdwMilliseconds);Thisfunctionreturnswhe

5、nthespecifiedobjectisinthesignaledstate(受信状态)orwhenthetime-outintervalelapses.该函数用于等待指定的对象(hHandle)变成受信状态。说明:在例说明:在例03ThreadDemo工程中,用于等待辅助线程对应的函工程中,用于等待辅助线程对应的函数数ThreadProc()执行完成。调用该函数将阻塞主线程。()执行完成。调用该函数将阻塞主线程。一个可执行对象有两种状态:未受信、受信。线程对象只有当线程结束才为受信态。第3章Win32程序的执行单元WaitForSingleObjecthHandleinHandletoth

6、eobject.Foralistoftheobjecttypeswhosehandlescanbespecified,seetheRemarkssection.dwMillisecondsinSpecifiesthetime-outinterval,inmilliseconds.Thefunctionreturnsiftheintervalelapses,eveniftheobjectsstateisnonsignaled.IfdwMillisecondsiszero,thefunctionteststheobjectsstateandreturnsimmediately.IfdwMillis

7、econdsisINFINITE,thefunctionstime-outintervalneverelapses.第3章Win32程序的执行单元线程的创建线程的创建例子程序第3章Win32程序的执行单元3.1.2 线程内核对象线程内核对象线程内核对象是一个包含了线程状态信息的数据结构。每次对CreateThread的成功调用,系统都会在内部为新的线程分配一个内核对象。系统对线程的管理是依靠访问线程内核对象来实现的。1.线程上下文线程上下文CONTEXT反映该线程上次运行时CPU寄存器的状态。第3章Win32程序的执行单元2.线程创建例子中使用计数线程创建例子中使用计数调用CreateThre

8、ad后,使用计数=2,线程函数返回,系统将使使用计数减少1,即使用计数=1,接下来又调用CloseHandle使使用计数减1,即最后使用计数=0,该内存空间被收回。第3章Win32程序的执行单元CONTEXT(上下文,即寄存器的状态),恢复现场必须使用使用计数(2):CreateThread返回句柄,相当于打开一次内核对象,促使该值+1,所以初始值=2;另外,OpenThread使该值+1,GetCurrentThread不会改变该值暂停次数(1):1表示处于暂停状态,这样就不会被调度到CPU中,给CreateThread时间对线程进行初始化。初始化之后,如果未传递CREATE_SUSPEND

9、ED(挂起)标志,暂停次数=0,该线程处于可调度状态。唤醒用ResumeThread(),该函数使暂停次数-1,挂起用SuspendThread(),该函数使暂停次数+1,一个线程可以被挂起若干次,这就需要唤醒同样次数才能使暂停次数=0,才能处于可调度状态,大约每隔20ms,进行一次时间片轮转,os选择新线程,将其上下文装入cpu寄存器,组织起运行。退出代码(STILL_ALIVE):即线程函数的返回值,可以用GetExitCodeThread得到线程退出代码,所以可以当作自定义的返回值来表示线程的执行结果。是否受信(FALSE):只有当线程结束时,该值才为TRUE第3章Win32程序的执行单

10、元3.1.3 线程的终止线程的终止线程终止的4种方法线程函数自然退出ExitThreadTerminateThread造成无法作清除工作,ExitProcess不提倡例子程序02ExitThread第3章Win32程序的执行单元3.1.4 线程的优先级线程的优先级每个线程被赋予一个优先级号,031,0最低,31最高,调度时选择最高的,并采用抢占式优先调度算法。eg:IEexplor的线程优先级就很高。设置优先级用SetThreadPriority()。BOOLSetThreadPriority(HANDLEhThread,intnPriority);第3章Win32程序的执行单元THREAD_

11、PRIORITY_TIME_CRITICAL实时THREAD_PRIORITY_HIGHEST最高THREAD_PRIORITY_ABOVE_NORMAL高于正常THREAD_PRIORITY_NORMAL正常THREAD_PRIORITY_BELOW_NORMAL低于正常THREAD_PRIORITY_LOWEST最低THREAD_PRIORITY_ABOVE_IDLE高于最低THREAD_PRIORITY_IDLE空闲第3章Win32程序的执行单元线程的优先级线程的优先级例子程序第3章Win32程序的执行单元3.1.5 C/C+运行期库运行期库在实际的开发过程中,一般使用c/c+运行期函数

12、_beginthreadx代替CreateThread函数。_beginthreadx首先申请一些用于线程同步的变量,然后调用CreateThreadVc+默认的c/c+运行期库不支持_beginthreadx,需要设置”Project/settings/c/c+/codegeneration/./选中multithreadDLL”即可。需要#include同样,使用_endthreadex代替ExitThread。该函数首先释放用于线程同步的变量,再调用ExitThread第3章Win32程序的执行单元3.2 线程同步线程同步同步可以保证在一个时间内只有一个线程对某个共享资源有控制权。临界区

13、对象事件内核对象线程局部存储(TLS)第3章Win32程序的执行单元3.2 线程同步线程同步解决同步问题的方法:临界区对象:线程独占,等待的线程挂起,不可调度互锁函数:单一变量同步问题事件内核对象:是否”受信”,通知信号量内核对象:信号量计数,多个线程共享,用于Socket(套接字)程序中线程同步互斥内核对象:线程独占,等待的线程可调度,用于保护内存第3章Win32程序的执行单元3.2.1 临界区对象临界区对象1.为什么要线程同步?当多个线程在同一个进程中执行时,可能有不止一个线程同时执行同一段代码,访问同一段内存中的数据。线程同步产生的问题一个错误的例子03ConntErr线程函数Threa

14、dFunc同时增加全局变量g_nCount1和g_nConnt2的计数,原则上两个变量的值应该相等,但由于是两个线程同时访问这两个全局变量,最终g_nCount1和g_nConnt2的值却不相等。第3章Win32程序的执行单元3.2.1 临界区对象临界区对象1.为什么要线程同步?多线程同步要能保证在一个线程占有公共资源的时候,其他线程不会再占有这个资源。解决同步问题,就要保证整个存取过程的独占性。第3章Win32程序的执行单元2.使用临界区对象使用临界区对象临界区对象是定义在数据段中的一个CRITICAL_SECTION结构,Windows内部使用这个结构纪录一些同步信息,确保在同一时间只有一

15、个线程访问该数据段中的数据。第3章Win32程序的执行单元使用临界区对象使用临界区对象voidInitializeCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);ParameterslpCriticalSectioninPointertothecriticalsectionobject.初始化临界区第3章Win32程序的执行单元使用临界区对象使用临界区对象voidEnterCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);ParameterslpCriticalSectioninP

16、ointertothecriticalsectionobject.申请进入临界区第3章Win32程序的执行单元使用临界区对象使用临界区对象voidLeaveCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);ParameterslpCriticalSectioninPointertothecriticalsectionobject.将临界区交还给Windows,离开临界区第3章Win32程序的执行单元使用临界区对象使用临界区对象voidDeleteCriticalSection(LPCRITICAL_SECTIONlpCriticalSec

17、tion);ParameterslpCriticalSectioninPointertothecriticalsectionobject.整个程序不再使用临界区的时候,将临界区删除第3章Win32程序的执行单元使用临界区对象使用临界区对象使用方法说明及程序例子03CriticalSection临界区对象能够很好的保护共享数据,但是它不能够用于进程之间资源的锁定,因为它不是内核对象,如果要在进程间维持线程的同步,可以使用事件内核对象。第3章Win32程序的执行单元3.2.2 互锁函数互锁函数互锁函数为同步访问多线程共享变量提供了一个简单的机制。如果变量在共享内存,不同进程的线程也可以使用此机制。

18、互锁函数包括:InterlockedIncrementInterlockedDecrementInterlockedExchangeAddInterlockedExchangePointer第3章Win32程序的执行单元互锁函数互锁函数TheInterlockedIncrementfunctionincrements(increasesbyone)thevalueofthespecified32-bitvariableandcheckstheresultingvalue.Thefunctionpreventsmorethanonethreadfromusingthesamevariablesi

19、multaneously.程序例子03InterlockDemo第3章Win32程序的执行单元while(g_bContinue):InterlockedIncrement(long*)&g_nCount1);:InterlockedIncrement(long*)&g_nCount2);在主线程中等待子线程的结束,子线程的结束条件是g_bContinue=false,这就保证了在一个子线程中,g_nCount1和g_nCount2执行了相同多次。产生不一致的唯一原因是加1的操作被打断第3章Win32程序的执行单元3.2.3 事件内核对象事件内核对象事件内核对象主要用于线程间通信(同步就是一种

20、简单的通信,指通信的数据量少)因为它是一个内核对象,所以可以跨进程使用,依靠通信,使各线程的工作协调进行,达到同步的目的。事件内核对象包括3个成员nUsageCount(使用计数)bManualReset(是否人工重置)bSignaled(是否受信)第3章Win32程序的执行单元事件内核对象事件内核对象使用WaitForSingleObject来判断事件内核对象是否受信,来达到通信的目的。使用使用CreateEvent函数创建事件对象。函数创建事件对象。HANDLECreateEvent(LPSECURITY_ATTRIBUTESlpEventAttributes,安全属性安全属性BOOLbM

21、anualReset,是否手动重置是否手动重置BOOLbInitialState,初始状态初始状态LPTSTRlpName);事件对象名称事件对象名称第3章Win32程序的执行单元事件内核对象事件内核对象设置事件对象名称是为了在其他地方(如:其他进程的事件对象名称是为了在其他地方(如:其他进程的线程中)使用线程中)使用OpenEvent或者或者CreateEvent获得此内核对获得此内核对象句柄。象句柄。HANDLE OpenEvent(DWORD dwDesiredAccess,访问权限访问权限 BOOL bInheritHandle,句柄是否被继承句柄是否被继承 LPCTSTR lpNam

22、e);事件对象名称事件对象名称第3章Win32程序的执行单元事件内核对象事件内核对象BOOLSetEvent(HANDLEhEvent);将事件对象状态设置为“受信”BOOLResetEvent(HANDLE hEvent);将事件对象状态设置为“未受信”程序例子第3章Win32程序的执行单元事件内核对象说明事件内核对象说明当一个自动重置的事件对象受信以后,windows仅允许一个等待在该事件上的线程变为可调度状态,然后就自动重置此事件对象为未受信状态。(如果使用setevent,则上述动作是紧接着setevent进行,然后才执行setevent后面的代码)当一个人工重置事件对象受信后,所有等

23、待在该对象上的线程都变为可调度状态。第3章Win32程序的执行单元线程同步问题实例线程同步问题实例问题描述:*父亲放苹果,儿子吃苹果,母亲放香蕉,女儿吃香蕉*在一个盘子之中只能放一样水果,苹果或香蕉*创建4个线程,分别代表父亲、儿子、母亲和女儿。主线程做初始化和收尾工作第3章Win32程序的执行单元/放苹果UINTWINAPIPutAppleThread(PVOIDpvParam)for(inti=0;i10;i+)WaitForSingleObject(g_dish,INFINITE);WaitForSingleObject(g_putApple,INFINITE);coutputapple

24、!n;SetEvent(g_eatApple);Sleep(5);return0;第3章Win32程序的执行单元/放香蕉UINTWINAPIPutBananaThread(PVOIDpvParam)for(inti=0;i10;i+)WaitForSingleObject(g_dish,INFINITE);WaitForSingleObject(g_putBanana,INFINITE);coutputbanana!n;SetEvent(g_eatBanana);Sleep(5);return0;第3章Win32程序的执行单元/吃苹果UINTWINAPIEatAppleThread(PVOID

25、pvParam)for(inti=0;i10;i+)WaitForSingleObject(g_eatApple,INFINITE);couteatapple!n;SetEvent(g_putApple);SetEvent(g_dish);return0;第3章Win32程序的执行单元/吃香蕉UINTWINAPIEatBananaThread(PVOIDpvParam)for(inti=0;i10;i+)WaitForSingleObject(g_eatBanana,INFINITE);coutch;return0;第3章Win32程序的执行单元3.2.6 线程局部存储线程局部存储(TLS)线

26、程局部存储(thread-localstorage,TLS)是一个使用很方便的存储线程局部数据的系统。利用TLS机制可以为进程中所有的线程关联若干个数据,各个线程通过由TLS分配的全局索引来访问与自己关联的数据。这样,每个线程都可以有线程局部的静态存储数据。第3章Win32程序的执行单元线程局部存储线程局部存储(TLS)第3章Win32程序的执行单元线程局部存储线程局部存储(TLS)动态使用TLS的典型步骤如下。(1)主线程调用TlsAlloc函数为线程局部存储分配索引,函数原型为:DWORDTlsAlloc(void);/返回一个TLS索引第3章Win32程序的执行单元线程局部存储线程局部存

27、储(TLS)系统为每一个进程都维护着一个长度为TLS_MINIMUM_AVAILABLE的位数组,TlsAlloc的返回值就是数组的一个下标(索引)。这个位数组的惟一用途就是记忆哪一个下标在使用中。初始状态下,此位数组成员的值都是FREE,表示未被使用。当调用TlsAlloc的时候,系统会挨个检查这个数组中成员的值,直到找到一个值为FREE的成员。把找到的成员的值由FREE改为INUSE后,TlsAlloc函数返回该成员的索引。如果不能找到一个值为FREE的成员,TlsAlloc函数就返回TLS_OUT_OF_INDEXES(在WinBase.h文件中定义为1),意味着失败。第3章Win32程

28、序的执行单元线程局部存储线程局部存储(TLS)(2)每个线程调用TlsSetValue和TlsGetValue设置或读取线程数组中的值,函数原型为:BOOLTlsSetValue(DWORDdwTlsIndex,/TLS索引LPVOIDlpTlsValue/要设置的值);LPVOIDTlsGetValue(DWORDdwTlsIndex);/TLS索引第3章Win32程序的执行单元线程局部存储线程局部存储(TLS)TlsSetValue和TlsGetValue分别用于设置和取得线程数组中的特定成员的值,而它们使用的索引就是TlsAlloc函数的返回值。这就充分说明了进程中惟一的位数组和各线程数

29、组的关系。例如,TlsAlloc返回3,那就说明索引3被此进程中的每一个正在运行的和以后要被创建的线程保存起来,用以访问各自线程数组中对应的成员的值。第3章Win32程序的执行单元线程局部存储线程局部存储(TLS)(3)主线程调用TlsFree释放局部存储索引。函数的惟一参数是TlsAlloc返回的索引。利用TLS可以给特定的线程关联一个数据。比如下面的例子将每个线程的创建时间与该线程关联了起来,这样,在线程终止的时候就可以得到线程的生命周期第3章Win32程序的执行单元线程局部存储线程局部存储(TLS)程序例子第3章Win32程序的执行单元实例实例多线程文件搜索器多线程文件搜索器struct

30、CDirectoryNode:publicCNoTrackObjectCDirectoryNode*pNext;/CTypedSimpleList类模板要使用此成员,指向下一个节点的指针charszDirMAX_PATH;/要查找的目录;选择从CNoTrackObject类继承主要是为方便。当创建对象时,CNoTrackObject类中重载版本的operatornew会自动将对象里各成员的值初始化为0。第3章Win32程序的执行单元classCRapidFinderpublic:CRapidFinder(intnMaxThread);virtualCRapidFinder();BOOLChec

31、klpsz);intm_nResultCount;/结果数目intm_nThreadCount;/活动线程数目CTypedSimpleList m_listDir;/目录列表CRITICAL_SECTIONm_cs;/关键代码段constintm_nMaxThread;/最大线程数目charm_szMatchNameMAX_PATH;/要搜索的文件HANDLEm_hDirEvent;/向m_listDir中添加新的目录后置位(受信)HANDLEm_hExitEvent;/各搜索线程将要退出时置位(受信);第3章Win32程序的执行单元AfxBeginThreadAfxBeginThreadcr

32、eatesanewCWinThreadobject,callsitsCreateThreadfunctiontostartexecutingthethread,andreturnsapointertothethread没有返回线程句柄。CWinThread*AfxBeginThread(AFX_THREADPROCpfnThreadProc,LPVOIDpParam,intnPriority=THREAD_PRIORITY_NORMAL,UINTnStackSize=0,DWORDdwCreateFlags=0,LPSECURITY_ATTRIBUTESlpSecurityAttrs=NULL);

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


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