欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【内核原理与实现 007】ETHREAD 结构体属性介绍

程序员文章站 2022-07-13 10:52:30
...
typedef struct _ETHREAD {
    KTHREAD Tcb;

    // 线程创建时间
    LARGE_INTEGER CreateTime;

    union {
        // 线程退出时间
        LARGE_INTEGER ExitTime;
        
        // 用于跨进程通信
        LIST_ENTRY LpcReplyChain;
        
        // 带键事件等待链表  
        LIST_ENTRY KeyedWaitChain;
    };
    union {
        // 线程退出状态
        NTSTATUS ExitStatus;
        
        // WRK不使用
        PVOID OfsChain;
    };

    //
    // Registry
    //

    // PCM_POST_BLOCK 链表头,用于线程向配置管理器登记注册表键的变化通知
    LIST_ENTRY PostBlockList;

    //
    // Single linked list of termination blocks
    //

    union {
        //
        // List of termination ports
        //

        // 线程退出时,系统通知所有已经登记过要接收其终止事件的端口
        PTERMINATION_PORT TerminationPort;

        //
        // List of threads to be reaped. Only used at thread exit
        //

        // 线程退出时,该节点挂到 PsReaperListHead 链表上,在线程回收器(reaper)
        // 的工作项目(WorkItem)中该线程的内核栈得以收回。
        struct _ETHREAD *ReaperLink;

        //
        // Keyvalue being waited for
        //
        
        // 带键事件的键值
        PVOID KeyedWaitValue;

    };

    // 定时器链表自旋锁
    KSPIN_LOCK ActiveTimerListLock;
    
    // 包含当前线程的所有定时器
    LIST_ENTRY ActiveTimerListHead;

    // 线程唯一标识符,由两部分组成,UniqueProcess 和 UniqueThread,
    // UniqueProcess 等于所属进程的 UniqueProcessId ,UniqueThread 等于
    // 此线程对象在进程句柄表中的句柄
    CLIENT_ID Cid;

    //
    // Lpc
    //

    union {
        // LPC应答通知
        KSEMAPHORE LpcReplySemaphore;
        
        // 用于处理带键的事件
        KSEMAPHORE KeyedWaitSemaphore;
    };

    // 通过最低位区分使用哪个,参见 base\ntos\lpc\lpcp.h 中的 LpcpGetThreadMessage 
    // 和 LpcpGetThreadPort 宏
    union {
        // 指向 LPCP_MESSAGE 的指针,包含LPC应答消息
        PVOID LpcReplyMessage;          // -> Message that contains the reply
        
        // LPC 等待端口
        PVOID LpcWaitingOnPort;
    };

    //
    // Security
    //
    //
    //    Client - If non null, indicates the thread is impersonating
    //        a client.
    //

    // 线程的模仿信息
    PPS_IMPERSONATION_INFORMATION ImpersonationInfo;

    //
    // Io
    //

    // 此链表包含当前线程所有正在处理但尚未完成的I/O请求(IRP对象)
    LIST_ENTRY IrpList;

    //
    //  File Systems
    //

    // 指向线程的*IRP,它或者指向NULL,或指向一个IRP,或包含了 fsrtl.h 中定义的标记
    // FSRTL_FAST_IO_TOP_LEVEL_IRP 或FSRTL_FSP_TOP_LEVEL_IRP ,仅当一个线程
    // 的I/O调用层次中最*的组件是文件系统时,TopLevelIrp 域才指向当前 IRP
    ULONG_PTR TopLevelIrp;  // either NULL, an Irp or a flag defined in FsRtl.h
    
    // 指向一个待检验的设备对象,当磁盘或CD-ROM设备驱动发现自从上一次该线程访问该设备以来,该
    // 设备似乎发生了变化,就会设置此域,从而使最高层的驱动程序,如文件系统,可以检查到设备的变化
    struct _DEVICE_OBJECT *DeviceToVerify;

    // 当前线程所属的进程,线程初始化时赋值(应该是指父进程,和ApcState里的要有所区分)
    // THREAD_TO_PROCESS 宏就是通过此成员实现的
    PEPROCESS ThreadsProcess;
    
    // 线程的启动地址,这是真正的线程启动地址,包含的通常是系统DLL中的线程启动地址,因而
    // 往往是相同的(譬如kernel32.dll 中的BaseProcessStart 或BaseThreadStart 函数)
    PVOID StartAddress;
    
    // 当windows子系统线程接收LPC消息时,它的Win32StartAddress 域也会被修改
    union {
        // windows子系统的启动地址,即 CreateThread API 接收到的线程启动地址
        PVOID Win32StartAddress;
        
        // 接收到的LPC消息的ID,此域仅当 SameThreadApcFlags 域中的 
        // LpcReceivedMsgIdValid 位被置上的时候才有效
        ULONG LpcReceivedMessageId;
    };
    //
    // Ps
    //

    // 冗余设计,链接所属进程的所有线程
    LIST_ENTRY ThreadListEntry;

    //
    // Rundown protection structure. Acquire this to do cross thread
    // TEB, TEB32 or stack references.
    //

    // 线程停止保护锁,跨线程引用 TEB 结构或者挂起线程等操作需要获得此锁才能进行,
    // 以免在操作过程中线程被销毁
    EX_RUNDOWN_REF RundownProtect;

    //
    // Lock to protect thread impersonation information
    //
    
    // 推锁,保护线程数据属性,例如 PspLockThreadSecurityExclusive 和
	// PspLockThreadSecurityShared 利用该域来保护线程的安全属性
    EX_PUSH_LOCK ThreadLock;

    // 指明当前线程正在等待对一个消息的应答
    ULONG LpcReplyMessageId;    // MessageId this thread is waiting for reply to

    // 指明了在一次I/O操作中读取多少个页面,用于页面交换文件和内存映射文件的读操作
    ULONG ReadClusterSize;

    //
    // Client/server
    //

    // 线程访问权限,详见 public\sdk\inc\ntpsapi.h 中的宏THREAD_<XXX>,
    // 例如 THREAD_TERMINATE 代表终止线程的权限
    ACCESS_MASK GrantedAccess;

    //
    // Flags for cross thread access. Use interlocked operations
    // via PS_SET_BITS etc.
    //

    //
    // Used to signify that the delete APC has been queued or the
    // thread has called PspExitThread itself.
    //

    #define PS_CROSS_THREAD_FLAGS_TERMINATED           0x00000001UL

    //
    // Thread create failed
    //

    #define PS_CROSS_THREAD_FLAGS_DEADTHREAD           0x00000002UL

    //
    // Debugger isn't shown this thread
    //

    #define PS_CROSS_THREAD_FLAGS_HIDEFROMDBG          0x00000004UL

    //
    // Thread is impersonating
    //

    #define PS_CROSS_THREAD_FLAGS_IMPERSONATING        0x00000008UL

    //
    // This is a system thread
    //

    #define PS_CROSS_THREAD_FLAGS_SYSTEM               0x00000010UL

    //
    // Hard errors are disabled for this thread
    //

    #define PS_CROSS_THREAD_FLAGS_HARD_ERRORS_DISABLED 0x00000020UL

    //
    // We should break in when this thread is terminated
    //

    #define PS_CROSS_THREAD_FLAGS_BREAK_ON_TERMINATION 0x00000040UL

    //
    // This thread should skip sending its create thread message
    //
    #define PS_CROSS_THREAD_FLAGS_SKIP_CREATION_MSG    0x00000080UL

    //
    // This thread should skip sending its final thread termination message
    //
    #define PS_CROSS_THREAD_FLAGS_SKIP_TERMINATION_MSG 0x00000100UL

    union {

        // 针对跨线程访问的标志位,详见下面的位域结构体
        ULONG CrossThreadFlags;

        //
        // The following fields are for the debugger only. Do not use.
        // Use the bit definitions instead.
        //

        struct {
            ULONG Terminated              : 1;	// 线程已执行终止操作
            ULONG DeadThread              : 1;	// 创建失败
            ULONG HideFromDebugger        : 1;	// 该线程对调试器不可见
            ULONG ActiveImpersonationInfo : 1;	// 线程正在模仿
            ULONG SystemThread            : 1;	// 系统线程
            ULONG HardErrorsAreDisabled   : 1;	// 硬件错误无效
            ULONG BreakOnTermination      : 1;	// 调试器在线程终止时停下该线程
            ULONG SkipCreationMsg         : 1;	// 不向调试器发送创建消息
            ULONG SkipTerminationMsg      : 1;	// 不向调试器发送终止消息
        };
    };

    //
    // Flags to be accessed in this thread's context only at PASSIVE
    // level -- no need to use interlocked operations.
    //

    union {
        // 一些只有在最低中断等级(0 被动级别)上才可以访问的标志位,并且只能被该线程自身访问
        // 所以对这些标志位的访问不需要互锁操作
        ULONG SameThreadPassiveFlags;

        struct {

            //
            // This thread is an active Ex worker thread; it should
            // not terminate.
            //

            ULONG ActiveExWorker : 1;
            ULONG ExWorkerCanWaitUser : 1;
            ULONG MemoryMaker : 1;

            //
            // Thread is active in the keyed event code. LPC should not run above this in an APC.
            //
            ULONG KeyedEventInUse : 1;
        };
    };

    //
    // Flags to be accessed in this thread's context only at APC_LEVEL.
    // No need to use interlocked operations.
    //

    union {
        // 一些在APC中断级别上被该线程自身访问的标志位,同样不需要互锁
        ULONG SameThreadApcFlags;
        struct {

            //
            // The stored thread's MSGID is valid. This is only accessed
            // while the LPC mutex is held so it's an APC_LEVEL flag.
            //

            BOOLEAN LpcReceivedMsgIdValid : 1;
            BOOLEAN LpcExitThreadCalled   : 1;
            BOOLEAN AddressSpaceOwner     : 1;
            BOOLEAN OwnsProcessWorkingSetExclusive  : 1;
            BOOLEAN OwnsProcessWorkingSetShared     : 1;
            BOOLEAN OwnsSystemWorkingSetExclusive   : 1;
            BOOLEAN OwnsSystemWorkingSetShared      : 1;
            BOOLEAN OwnsSessionWorkingSetExclusive  : 1;
            BOOLEAN OwnsSessionWorkingSetShared     : 1;

            #define PS_SAME_THREAD_FLAGS_OWNS_A_WORKING_SET    0x000001F8UL

            BOOLEAN ApcNeeded                       : 1;
        };
    };

    // 指示是否仅仅前向聚集
    BOOLEAN ForwardClusterOnly;
    
    // 控制页面交换的聚集与否
    BOOLEAN DisablePageFaultClustering;
    
    // 正在进行之中的页面错误数量
    UCHAR ActiveFaultCount;

#if defined (PERF_DATA)
    ULONG PerformanceCountLow;
    LONG PerformanceCountHigh;
#endif

} ETHREAD, *PETHREAD;