windows进程和线程.ppt

上传人:sh****n 文档编号:6570451 上传时间:2020-02-29 格式:PPT 页数:48 大小:864.81KB
返回 下载 相关 举报
windows进程和线程.ppt_第1页
第1页 / 共48页
windows进程和线程.ppt_第2页
第2页 / 共48页
windows进程和线程.ppt_第3页
第3页 / 共48页
点击查看更多>>
资源描述
第4章Windows进程和线程 chensq8808 主要内容 windows进程windows线程线程同步 一 进程 进程是不活泼的 若要使进程完成某项操作 它必须至少拥有一个线程 该线程负责执行包含在进程的地址空间中的代码 实际上 单个进程可能包含若干个线程 所有这些线程都 同时 执行进程地址空间中的代码 为此 每个线程都有它自己的一组CPU寄存器和它自己的堆栈 每个进程至少拥有一个线程 来执行进程的地址空间中的代码 当创建一个进程时 系统会自动创建它的第一个线程 称为主线程 然后 该线程可以创建子线程 而这些子线程又能创建更多的子线程 大约20ms Windows进程操作相关API CreateProcess 进程创建ExitProcess 或TerminateProcess 进程退出ExitProcess 终止一个进程和它的所有线程 它的终止操作是完整的 包括关闭所有对象句柄 它的所有线程等 TerminateProcess 终止指定的进程和它的所有线程 它的终止操作是不完整的 如 不向相关DLL通报关闭情况 通常只用于异常情况下对进程的终止 范例 进程创建与退出 进程创建与退出 二 线程 线程 thread 是为了提高系统内程序的并发执行程度而提出来的概念 它是比进程更小的能够独立运行的基本单位 线程是一个轻量级实体 light weightentity 它的结构 threadstructure 相对简单 在切换速度上非常得快 同一进程中的线程切换不会引起进程的切换 对于并行计算来讲 有效的利用线程能够改善计算的效率 简化计算的复杂性 线程也是由两个部分组成的 一个是线程的内核对象 操作系统用它来对线程实施管理 另一个是线程堆栈 它用于维护线程在执行代码时需要的所有函数参数和局部变量 2 1线程组成 比较进程与线程 同一进程中的线程共享如下内容 全局变量堆数据打开的文件句柄用户及用户组ID但每个线程具有独立的 线程ID堆栈error变量优先级 几点提示 同一进程中的线程共享这个进程的全部资源与地址空间 这样 多个线程确实能够非常容易地互相通信 Windows支持的是内核级线程 由内核完成创建和撤销 内核维护进程和线程的上下文信息 线程切换由内核完成 一个线程发起系统调用而阻塞 不会影响其他线程的运行 时间片分配给线程 所以多线程的进程获得更多CPU时间 Windows是个抢占式多线程系统 依赖优先级 2 2创建线程的方法与区别 针对C C MFC 1 CreateThread WIN32API函数2 beginthreadex MS对CRuntime库的扩展SDK函数3 AfxBeginThread MFC中线程创建的MFC函数 beginthreadex 初始化 CreateThread AfxBeginThread 线程对象初始化 beginthreadex CreateThread 提供操作系统级别的创建线程的操作 且仅限于工作者线程 线程函数中不调用MFC和RTL的函数时 可以用CreateThread 其它情况不要轻易使用 以免内存泄漏 但它没有考虑 1 CRuntime库里面有一些函数使用了全局量 如果使用CreateThread的情况下使用这些C 运行库的函数 就会出现不安全的问题 而 beginthreadex为这些全局变量做了处理 典型的例子是strtok函数 2 MFC也需要知道新线程的创建 也需要做一些初始化工作 beginthreadex MS对CRuntime库的扩展SDK函数 首先针对CRuntime库做了一些初始化的工作 以保证CRuntime库工作正常 然后 调用CreateThread真正创建线程 仅使用RuntimeLibrary时 可以用 BegingThread beginthreadex函数在创建线程的时候分配了一个堆结构并和线程本身关联起来 这个结构叫做tiddata结构 线程创建时传入的线程入口函数地址就保存在这个结构中 另外 C运行时库中有些函数需要通过这个结构来保存和获取一些数据 比如说errno之类的线程全局变量 当一个线程调用一个要求tiddata结构的CRuntime库函数的时候 将发生下面的情况 CRuntime库函数试图TlsGetvalue获取线程数据块的地址 如果没有获取到 函数就会现场分配一个tiddata结构 并且和线程相关联 于是问题出现了 如果不通过 endthreadex函数来终结线程的话 这个结构将不会被撤销 内存泄漏就会出现了 但通常情况下 我们都不推荐使用 endthreadex函数来结束线程 因为里面包含了ExitThread调用 AfxBeginThread MFC中线程创建的MFC函数 首先创建了相应的CWinThread对象 然后调用CWinThread CreateThread 在CWinThread CreateThread中 完成了对线程对象的初始化工作 然后 调用 beginthreadex AfxBeginThread相比较更为安全 创建线程 它简化了操作或让线程能够响应消息 即可用于界面线程 也可以用于工作者线程 但要注意不要在一个MFC程序中使用 beginthreadex 或CreateThread 使用准则 如果线程函数中只调用Win32API 就放心用CreateThread 如果要用到CRuntime库 那么就要使用 beginthreadex 并且需要在编译环境中选择UseMultiThreadLib DLL MFC程序中使用AfxBeginThread 坚决不要使用 beginthread 无法创建带有安全属性的新线程 无法创建暂停的线程 也无法获得线程的ID值 2 3线程函数原型介绍 CreateThread createsaworkerthread 举例 beginthreadex createsaworkerthreadunsignedlong beginthreadex void security unsignedstack size Unsigned stdcall start address void Void arglist Unsignedinitflag Unsigned thrdaddr 举例 compilewith MT AfxBeginThread createsaworkerthreadCWinThread AfxBeginThread AFX THREADPROCpfnThreadProc LPVOIDpParam intnPriority THREAD PRIORITY NORMAL UINTnStackSize 0 DWORDdwCreateFlags 0 LPSECURITY ATTRIBUTESlpSecurityAttrs NULL 举例 AfxBeginThread createsauser interfacethreadCWinThread AfxBeginThread CRuntimeClass pThreadClass intnPriority THREAD PRIORITY NORMAL UINTnStackSize 0 DWORDdwCreateFlags 0 LPSECURITY ATTRIBUTESlpSecurityAttrs NULL 举例 2 4线程深入分析 1 线程的创建和初始化 调用CreateThread时 系统创建一个线程内核对象 该对象的初始使用计数是2 线程的内核对象的其他属性也被初始化 暂停计数被设置为1 退出代码始终为STILL ACTIVE 0 x103 该对象设置为nonsignaledstate 每个线程都有它自己的一组CPU寄存器 称为线程的上下文 线程的这组CPU寄存器保存在一个CONTEXT结构 在WinNT h头文件中定义 中 x86类型CPU对应的CONTEXT结构 指令指针 IP 和堆栈指针 SP 寄存器是线程上下文中两个最重要的寄存器 当线程的内核对象被初始化时 CONTEXT结构的堆栈指针寄存器被设置为线程堆栈上用来放置pfnStartAddr的地址 指令指针寄存器置为称为BaseThreadStart的函数的地址中 该函数包含在Kernel32 dll模块中 这也是实现CreateThread函数的地方 BaseThreadStart函数执行的基本操作 该函数实际上是线程开始执行的地方 2 C C 运行期库的考虑 当实现任何类型的编程项目时 必须知道将哪个库与你的项目相链接 如下图 为什么将一个库用于单线程应用程序 而将另一个库用于多线程程序 原因是 标准C运行期库是1970年问世的 它远远早于线程在任何应用程序上的应用 运行期库的发明者没有考虑到将C运行期库用于多线程应用程序的问题 3 线程终止运行若要终止线程的运行 可以使用下面的方法 线程函数返回 最好使用这种方法 通过调用ExitThread endthreadex AfxEndThread函数 线程将自行撤消 最好不要使用这种方法 同一个进程或另一个进程中的线程调用TerminateThread函数 应该避免使用这种方法 包含线程的进程终止运行 应该避免使用这种方法 线程函数返回 通过设置条件 如信号对象 事件对象等 始终都应该将线程设计成这样的形式 这是确保所有线程资源被正确地清除的唯一办法 如果线程能够返回 就可以确保下列事项的实现 在线程函数中创建的所有C 对象均将通过它们的撤消函数正确地撤消 操作系统将正确地释放线程堆栈使用的内存 系统将线程的退出代码 在线程的内核对象中维护 设置为线程函数的返回值 系统将递减线程内核对象的使用计数 当线程终止运行时 会发生下列操作 AllUserobjecthandlesownedbythethreadarefreed Thethread sexitcodechangesfromSTILL ACTIVEtothecodepassedtoExitThreadorTerminateThread Thestateofthethreadkernelobjectbecomessignaled 这样 可以在主线中利用WaitForSingleObject函数等待线程终止运行 Ifthethreadisthelastactivethreadintheprocess thesystemconsiderstheprocessterminatedaswell Thethreadkernelobject susagecountisdecrementedby1 2 5线程的调度 优先级和亲缘性 使用VC 6 0的Spy 这个工具 可以查看进程中线程的情况 2 5 1线程的暂停 恢复 休眠 切换函数 1 暂停和恢复线程的运行 2 睡眠 线程也能告诉系统 它不想在某个时间段内被调度 这是通过调用Sleep函数来实现的 关于Sleep函数 下面几个重要问题值得注意 调用Sleep 可使线程自愿放弃它剩余的时间片 Sleep n 系统将在大约的n毫秒数内使线程不可调度 也可能是数秒钟或者数分钟 记住 Windows不是个实时操作系统 虽然线程可能在规定的时间被唤醒 但是它能否做到 取决于系统中还有什么操作正在进行 Sleep 0 这将告诉系统 调用线程将释放剩余的时间片 并迫使系统调度另一个线程 但是 系统可以对刚刚调用Sleep的线程重新调度 如果不存在多个拥有相同优先级的可调度线程 就会出现这种情况 3 切换到另一个线程 BOOLSwitchToThread VOID 调用SwitchToThread函数与调用Sleep 0 相似 差别是SwitchToThread允许优先级较低的线程运行 即使低优先级线程迫切需要CPU时间 Sleep也能够立即对调用线程重新进行调度 2 5 2线程的优先级 每个线程都会被赋予一个从0 最低 到31 最高 的优先级号码 高优先级线程将抢在低优先级线程之前运行 不管低优先级线程正在运行什么 当设计一个应用程序时 你应该考虑到还有什么别的应用程序会与你的应用程序一道运行 然后 应该根据你的应用程序中的线程应该具备何种响应性 选择一个优先级类 一旦选定了优先级类之后 就不必考虑你的应用程序与其他应用程序之间的关系 只需要集中考虑你的应用程序中的各个线程的相对优先级 先确定应用程序优先级类 再确定线程相对优先级 Windows支持6个优先级类 Windows支持7个相对的线程优先级 进程优先级类和线程相对优先级的映射 注意 如果改变了进程的优先级类 线程的相对优先级不变 但是它的优先级的等级却发生了变化 2 5 3优先级编程 进程优先级类的设置方法 1 当调用CreateProcess时 可以在fdwCreate参数中传递需要的优先级类 下表所示 2 调用SetPriorityClass来改变进程自己的优先级类 BOOLSetPriorityClass HANDLEhProcess handletoprocessDWORDdwPriorityClass priorityclass 例如 SetPriorityClass GetCurrentProcess HIGH PRIORITY CLASS 查看例子 另外 DWORDGetPriorityClass HANDLEhProcess retrievesthepriorityclassforthespecifiedprocess 线程相对优先级的设置方法 当一个线程刚刚创建时 它的相对线程优先级总是设置为正常优先级 若要设置和获得线程的相对优先级 必须调用下面的函数 BOOLSetThreadPriority HANDLEhThread intnPriority intGetThreadPriority HANDLEhThread 举例 2 5 4动态提升线程优先级 进程优先级类和线程相对优先级的映射值称为线程的基本优先级 系统常常要动态提高线程的优先级 以便对窗口消息或读取磁盘等I O事件作出响应 例如 在高优先级类进程中的一个正常优先级等级的线程的基本优先级等级是13 如果用户按下一个操作键 系统就会将一个WM KEYDOWN消息放入线程的队列中 由于一个消息已经出现在线程的队列中 因此该线程就是可调度的线程 此外 键盘设备驱动程序也能够告诉系统暂时提高线程的优先级等级 该线程的优先级等级可能提高2级 其当前优先级等级改为15 系统在优先级为15时用一个时间片对该线程进行调度 一旦该时间片结束 系统便将线程的优先级递减1 使下一个时间片的线程优先级降为14 该线程的第三个时间片按优先级等级13来执行 如果线程要求执行更多的时间片 均按它的基本优先级等级13来执行 注意 线程的当前优先级等级决不会低于线程的基本优先级等级 系统只能为基本优先级等级在1至15之间的线程提高其优先级等级 这个范围称为动态优先级范围 系统决不会将线程的优先级等级提高到实时范围 高于15 下面两个函数 能够使系统的动态提高线程优先级等级的功能不起作用 SetProcessPriorityBoost 负责告诉系统激活或停用进行中的所有线程的优先级提高功能 SetThreadPriorityBoost 则让你激活或停用单个线程的优先级提高功能 2 5 5亲缘性 按照默认设置 当系统将线程分配给处理器时 Windows2K XP 2003使用软亲缘性来进行操作 这意味着如果所有其他因素相同的话 它将设法在它上次运行的那个处理器上运行线程 让线程留在单个处理器上 有助于重复使用仍然在处理器的内存高速缓存中的数据 2 6线程同步 线程同步技术 作业 阐述线程的本质和调度 掌握经典的4中同步技术 并 1 用标准C 语言和互斥对象 实现一个生产 消费系统模型 2 用MFC和关键区同步技术 实现一个生产 消费系统模型
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


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

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


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