zoukankan      html  css  js  c++  java
  • windows核心编程学习笔记(二)Wait For Kernel Object(s)

    一.概述
    可以被wait的东东有:
  • Change notification
  • Console input
  • Event  ->小心,如果是AutoResetEvent,那么在signed之后,WaitForXXObject返回之前,会再次被unsigned.
  • Job
  • Memory resource notification
  • Mutex
  • Process
  • Semaphore
  • Thread
  • Waitable timer

    0.多个线程WaitForSingleObject()同一个AutoResetEvent,那么此对象signed之后,哪个线程变为可调度呢?
    1.进程句柄、线程句柄、事件等等内核对象,正常使用时(运行时)都是unsigned的,完蛋了才signed;
    2.完蛋了的Object才能使WaitForSingleObject或WaitForMultipleObjects返回(当然超时或出错除外);
    3.WaitForMultipleObjects如果不是WaitAll,那么句柄数组中有一个signed的就会返回,返回值 dwResult - WAIT_OBJECT_0 表示signed的句柄的索引值;
    4.ManualResetEvent和AutoResetEvent的差别在于:AutoResetEvent可以自动调度所有需要读写同一数据的线程,弊端是:无法确定谁先被调度;

    二.信标(semaphore)
          通过调用等待函数,传递负责保护资源的信标的句柄,线程就能够获得对该资源的访问权。从内部来说,该等待函数要检查信标的当前资源数量,如果它的值大于0(信标已经发出信号),那么计数器递减1,调用线程保持可调度状态。信标的出色之处在于它们能够以原子操作方式来执行测试和设置操作,这就是说,当向信标申请一个资源时,操作系统就要检查是否有这个资源可供使用,同时将可用资源的数量递减,而不让另一个线程加以干扰。只有当资源数量递减后,系统才允许另一个线程申请对资源的访问权。
           我的理解是:假设信标中有3可用资源,并且有5个线程在等待,那么就会有3个线程变为可调度,同时资源数减为0.那么还有2个线程仍在等待。此时,有个xx线程(或xx函数)准备好了一个可用资源,打算让等待中的线程处理该资源,那么此xx可以调用 ReleaseSemaphore(hSemaphore, 1, NULL); 来添加一个资源数。在这之后,等待中的一个线程立刻获得调度权限,信标内资源数再次减为0,剩余最后一个线程继续苦苦等待...
    注意事项:ReleaseSemaphore的第二个参数传入0将毫无效果,第三个参数也不会正确地返回原来的资源数量;

    三.互斥对象(Mutex)

           通过调用一个等待函数,并传递负责保护资源的互斥对象的句柄,线程就能够获得对共享资源的访问权。在内部,等待函数要检查线程的I D,以了解它是否是0(互斥对象发出通知信号)。如果线程I D是0,那么该线程I D被设置为调用线程的I D,递归计数器被设置为1,同时,调用线程保持可调度状态。

             如果等待函数发现I D不是0(不发出互斥对象的通知信号),那么调用线程便进入等待状态。系统将记住这个情况,并且在互斥对象的I D重新设置为0时,将线程I D设置为等待线程的I D,将递归计数器设置为1,并且允许等待线程再次成为可调度线程。与所有情况一样,对互斥内核对象进行的检查和修改都是以原子操作方式进行的。

            书里说的已经很明白了~~~
    互斥对象的特别之处:
           互斥对象的结构(我猜的)中有一个当前归属的线程ID成员,和使用计数成员。当该对象归属于某一个线程(A)时(即WaitForXXObject成功),那么dwID就设置为调度线程A的ID,同时dwCount设置为1。如果该线程再次WaitForXX,那么函数会立即返回,因为是同一dwID嘛,但是dwCount会递增1。如果此时另外一个线程B也来凑热闹,那么会进入睡眠状态,直到A调用ReleaseMutex相应的次数,那么dwID将设置为B的id,且dwCount为1。也就是说只要dwID不为0,那么该对象绝对是unsigned的;如果为0,那么该对象必定是signed的。
            当一个线程拥有了互斥对象,但是却意外终止了(例如TerminateThread --),没有来得及调用ReleaseMutex,那么系统将视为该对象已经被释放,其他等待的线程之一将获得调度,只不过WaitForxx返回值是WAIT_ABANDONED,表明上一个线程是非正常中止的,你(此线程)看着办吧。

    四.其它好用的函数

    1.WaitForInputIdle:传递一个进程句柄给它,那么就可以等待直到该进程创建完毕,显示了窗口,并且等待用户进行输入——这太有用了,当你的程序创建了一个子进程的时候,很可能需要知道子进程何时完全创建完毕,有了它,一切变得那么简单!
    2.MsgWaitForMultipleObjects(Ex):我的理解是,这两个函数可以用在同时处理消息的线程中,这样当句柄们都signed或者来了消息时都可以返回.具体和时返回取决于dwWakeMask参数~;
    3.WaitForDebugEvent:等待调试事件,估计只有开发调试器时才可能用得到吧;
    4.SignalObjectAndWait:该函数允许同时执行2件事:第一件事是把hObjectToSignal 置为signed,第二件事是等待hObjectToWaitOn——多好,自己不用的东东Release掉,同时等待要用的东东。

    -本节完-

查看全文
  • 相关阅读:
    日报 18/05/29
    jsvascript === 和==的区别
    分享个数组
    ROC曲线绘制
    DLL中传递STL参数(如Vector或者list等)会遇到的问题[转载]
    利用JAX-WS 开发web服务
    菜鸟的成长之路——在清华特奖经验分享交流会上的演讲
    一段小代码的思考
    关于Vector中的元素中含有指针成员的情况
    关于职业规划——好帖【转载】
  • 原文地址:https://www.cnblogs.com/yoran/p/1086669.html
  • Copyright © 2011-2022 走看看