等待块(一)

_DISPATCHER_HEADER 结构

c 复制代码
//0x10 bytes (sizeof)
struct _DISPATCHER_HEADER
{
    union
    {
        struct
        {
            UCHAR Type;                                                     //0x0
            union
            {
                UCHAR TimerControlFlags;                                    //0x1
                struct
                {
                    UCHAR Absolute:1;                                       //0x1
                    UCHAR Coalescable:1;                                    //0x1
                    UCHAR KeepShifting:1;                                   //0x1
                    UCHAR EncodedTolerableDelay:5;                          //0x1
                };
                UCHAR Abandoned;                                            //0x1
                UCHAR Signalling;                                           //0x1
            };
            union
            {
                UCHAR ThreadControlFlags;                                   //0x2
                struct
                {
                    UCHAR CpuThrottled:1;                                   //0x2
                    UCHAR CycleProfiling:1;                                 //0x2
                    UCHAR CounterProfiling:1;                               //0x2
                    UCHAR Reserved:5;                                       //0x2
                };
                UCHAR Hand;                                                 //0x2
                UCHAR Size;                                                 //0x2
            };
            union
            {
                UCHAR TimerMiscFlags;                                       //0x3
                struct
                {
                    UCHAR Index:1;                                          //0x3
                    UCHAR Processor:5;                                      //0x3
                    UCHAR Inserted:1;                                       //0x3
                    volatile UCHAR Expired:1;                               //0x3
                };
                UCHAR DebugActive;                                          //0x3
                struct
                {
                    UCHAR ActiveDR7:1;                                      //0x3
                    UCHAR Instrumented:1;                                   //0x3
                    UCHAR Reserved2:4;                                      //0x3
                    UCHAR UmsScheduled:1;                                   //0x3
                    UCHAR UmsPrimary:1;                                     //0x3
                };
                UCHAR DpcActive;                                            //0x3
            };
        };
        volatile LONG Lock;                                                 //0x0
    };
    LONG SignalState;                                                       //0x4
    struct _LIST_ENTRY WaitListHead;                                        //0x8
}; 

在windows内核中,凡是头部以_DISPATCHER_HEADER 开始的对象都是被等待对象

如:

  • KTHREAD
  • KEVENT
  • KMUTANT(内核互斥体)
  • KSEMAPHORE
  • KTIMER
  • KQUEUE 等

_DISPATCHER_HEADER = 内核等待对象的公共头
Windows 等待机制里,线程是唯一的等待者;而带 _DISPATCHER_HEADER 的对象是可被等待的 dispatcher object,其中线程对象本身也属于可被等待对象。

等待者永远是线程;被等待者是 dispatcher object;线程对象本身既能等待别人,也能被别人等待。

KTHREAD._KWAIT_BLOCK

c 复制代码
//0x18 bytes (sizeof)
struct _KWAIT_BLOCK
{
    struct _LIST_ENTRY WaitListEntry;                                       //0x0
    struct _KTHREAD* Thread;                                                //0x8
    VOID* Object;                                                           //0xc
    struct _KWAIT_BLOCK* NextWaitBlock;                                     //0x10
    USHORT WaitKey;                                                         //0x14
    UCHAR WaitType;                                                         //0x16
    volatile UCHAR BlockState;                                              //0x17
}; 

线程一旦进入等待,内核就需要有个结构把这几个信息串起来:

  • 是谁在等(哪个线程)
  • 在等谁(哪个对象)
  • 这次等待属于哪种等待
  • 把它挂到哪个等待链表里

KWAIT_BLOCK 就是干这个的。它本质上是 线程 和 等待对象 之间的一条"挂接记录"。

字段解释

WaitListEntry

这是双向链表节点。

它的作用是把当前这个 KWAIT_BLOCK 挂到等待对象的 DISPATCHER_HEADER.WaitListHead 里。

也就是:"这个对象当前有哪些线程在等它",靠的就是这一串 KWAIT_BLOCK 链表。

Thread

指向正在等待的线程。

对象被置为 signaled 时,内核会通过这个字段知道:

应该唤醒哪一个线程。

Object

指向当前正在等待的对象。

这个对象通常就是某个 dispatcher object,比如:

  • event
  • semaphore
  • mutant / mutex
  • timer
  • thread

因为这些对象都带有 DISPATCHER_HEADER,所以都能维护等待链表。

NextWaitBlock

这是单向链表 把多个 KWAIT_BLOCK 串起来的指针。

它更偏向从线程这一侧去组织多个等待块。

当一个线程同时等待多个对象时,这些 KWAIT_BLOCK 可以通过 NextWaitBlock 组成链。

WaitKey

在 WaitAny / 多对象等待里,标识是第几个对象满足了等待。对应的值本质上就是该 KWAIT_BLOCK 在等待块数组里的 0 基索引。

WaitType

是枚举类型:

c 复制代码
typedef enum _WAIT_TYPE
{
	WaitAll,
	WaitAny
}WAIT_TYPE;
  • WaitAll:线程要等待所有对象都变成有信号状态
  • WaitAny:只要任意一个对象编程有信号状态即可。

BlockState

这是 等待块自身的状态。

它不是对象状态,也不是线程状态,而是这个 KWAIT_BLOCK 当前处于什么阶段。

相关推荐
超级大福宝1 小时前
VS Code Remote-SSH 因 RemoteForward 端口冲突导致连接失败的排查与解决
运维·服务器·windows·vscode·ssh
Vex2une1 小时前
Windows PowerShell 发展史:从命令行工具到自动化核心
windows·自动化运维·命令行·powershell·cmd·脚本语言·对象管道
怎么没有名字注册了啊13 小时前
Qt开发:MessageBox怎么调出标题栏那个问号按钮?
windows
李子红了时14 小时前
EncFS MP中文版汉化下载(免费文件加密工具)
windows·安全
辻弋20115 小时前
五年前的旅行视频糊成马赛克?Video2X用Real-ESRGAN逐帧重建细节,但只支持Windows、集显用户建议直接放弃
服务器·数据库·windows·游戏引擎·电脑
会飞的土拨鼠呀15 小时前
Windows 系统关闭虚拟内存文件pagefile.sys
windows
传奇开心果编程17 小时前
【Compose Multiplatform 跨端开发学与练】第7课 平台适配与互操作
android·windows·学习·ui·ios·kotlin·composer
工作10年+,存储芯片行业17 小时前
Linux NVMe 中断排查与性能优化:CPU 亲和性
linux·运维·服务器·windows·性能优化·ssd·pcie
lpfasd12318 小时前
WinSW在Win7上失败真相-实测与修复
windows·nginx
万山寒19 小时前
windows使用WinSW注册服务
windows