Windows内核原理与实现--Windows进程线程基本概念(1)

进程的一些基本概念

操作系统需要做的事情是:维护一个全局的进程表,记录下当前有哪些进程正在被执行,把时间分成适当的片段,设置时钟中断来完成,因而每次时钟中断到来时系统就会获得控制权,在进程间实施切换,即保留上一个进程的环境信息,恢复下一个执行环境。

一个典型布局的程序结构是这样的:

内存高地址 命令行 环境信息(随运行时确定)

调用栈(随控制流而变化)

堆(动态数据区)

未初始化的数据 喜闻乐见的bss(静态数据区)

已初始化的数据(静态数据区)

内存低地址 代码 text


线程的一些基本概念

线程有两种模型,用户级线程和内核级线程。用户级线程模型的优势是线程切换效率高,因为不涉及内核模式和用户模式之间的切换,并且应用程序可以采用合适自己特点的线程选择算法。内核级线程有可能应用各种算法来分配处理器时间,线程可以有优先级,高优先级的线程被优先执行。系统维护一个全局线程表,系统在适当的时候挂起一个正在执行的线程,这个适当的时候有多种可能:sleep、wait/select、硬中断或异常、线程终止。内核级线程的好处是,无需考虑自己霸占处理器而导致其他线程得不到处理器时间。代价是,所有线程切换都是在内核模式下完成的。对于在用户模式下运行的线程来说,一个线程被切换出去,下次再切换回来,需要从用户模式到内核模式,再从内核模式切换回用户模式。

线程调度算法可以分为非抢占式和抢占式。抢占式通过一个时钟中断来获得对处理器的控制权。有三种典型的线程调度算法:先到先服务算法,时间片轮转算法,优先级调度算法。Windows的调度算法是一个抢占式的、支持多处理器的优先级调度算法,每个处理器定义了一个链表数组,相同优先级的线程挂在同一个链表中,不同优先级的线程分别属于不同的链表。当一个线程满足条件时,它首先被挂到当前处理器的一个待分配的链表,调度器在适当的时候会把待分配的链表上的线程分配到了某个处理器的对应优先级的线程链表中。


Windows中进程和线程的数据姐欧冠


微内核层的进程和线程对象

首先看微内核的数据结构,KPROCESS和KTHREAD。这里以NT6内核为例

nt!_KPROCESS
   +0x000 Header           : _DISPATCHER_HEADER
   +0x018 ProfileListHead  : _LIST_ENTRY
   +0x028 DirectoryTableBase : Uint8B
   +0x030 ThreadListHead   : _LIST_ENTRY
   +0x040 ProcessLock      : Uint8B
   +0x048 Affinity         : _KAFFINITY_EX
   +0x070 ReadyListHead    : _LIST_ENTRY
   +0x080 SwapListEntry    : _SINGLE_LIST_ENTRY
   +0x088 ActiveProcessors : _KAFFINITY_EX
   +0x0b0 AutoAlignment    : Pos 0, 1 Bit
   +0x0b0 DisableBoost     : Pos 1, 1 Bit
   +0x0b0 DisableQuantum   : Pos 2, 1 Bit
   +0x0b0 ActiveGroupsMask : Pos 3, 4 Bits
   +0x0b0 ReservedFlags    : Pos 7, 25 Bits
   +0x0b0 ProcessFlags     : Int4B
   +0x0b4 BasePriority     : Char
   +0x0b5 QuantumReset     : Char
   +0x0b6 Visited          : UChar
   +0x0b7 Unused3          : UChar
   +0x0b8 ThreadSeed       : [4] Uint4B
   +0x0c8 IdealNode        : [4] Uint2B
   +0x0d0 IdealGlobalNode  : Uint2B
   +0x0d2 Flags            : _KEXECUTE_OPTIONS
   +0x0d3 Unused1          : UChar
   +0x0d4 Unused2          : Uint4B
   +0x0d8 Unused4          : Uint4B
   +0x0dc StackCount       : _KSTACK_COUNT
   +0x0e0 ProcessListEntry : _LIST_ENTRY
   +0x0f0 CycleTime        : Uint8B
   +0x0f8 KernelTime       : Uint4B
   +0x0fc UserTime         : Uint4B
   +0x100 InstrumentationCallback : Ptr64 Void
   +0x108 LdtSystemDescriptor : _KGDTENTRY64
   +0x118 LdtBaseAddress   : Ptr64 Void
   +0x120 LdtProcessLock   : _KGUARDED_MUTEX
   +0x158 LdtFreeSelectorHint : Uint2B
   +0x15a LdtTableLength   : Uint2B

nt!_KTHREAD
   +0x000 Header           : _DISPATCHER_HEADER
   +0x018 CycleTime        : Uint8B
   +0x020 QuantumTarget    : Uint8B
   +0x028 InitialStack     : Ptr64 Void
   +0x030 StackLimit       : Ptr64 Void
   +0x038 KernelStack      : Ptr64 Void
   +0x040 ThreadLock       : Uint8B
   +0x048 WaitRegister     : _KWAIT_STATUS_REGISTER
   +0x049 Running          : UChar
   +0x04a Alerted          : [2] UChar
   +0x04c KernelStackResident : Pos 0, 1 Bit
   +0x04c ReadyTransition  : Pos 1, 1 Bit
   +0x04c ProcessReadyQueue : Pos 2, 1 Bit
   +0x04c WaitNext         : Pos 3, 1 Bit
   +0x04c SystemAffinityActive : Pos 4, 1 Bit
   +0x04c Alertable        : Pos 5, 1 Bit
   +0x04c GdiFlushActive   : Pos 6, 1 Bit
   +0x04c UserStackWalkActive : Pos 7, 1 Bit
   +0x04c ApcInterruptRequest : Pos 8, 1 Bit
   +0x04c ForceDeferSchedule : Pos 9, 1 Bit
   +0x04c QuantumEndMigrate : Pos 10, 1 Bit
   +0x04c UmsDirectedSwitchEnable : Pos 11, 1 Bit
   +0x04c TimerActive      : Pos 12, 1 Bit
   +0x04c SystemThread     : Pos 13, 1 Bit
   +0x04c Reserved         : Pos 14, 18 Bits
   +0x04c MiscFlags        : Int4B
   +0x050 ApcState         : _KAPC_STATE
   +0x050 ApcStateFill     : [43] UChar
   +0x07b Priority         : Char
   +0x07c NextProcessor    : Uint4B
   +0x080 DeferredProcessor : Uint4B
   +0x088 ApcQueueLock     : Uint8B
   +0x090 WaitStatus       : Int8B
   +0x098 WaitBlockList    : Ptr64 _KWAIT_BLOCK
   +0x0a0 WaitListEntry    : _LIST_ENTRY
   +0x0a0 SwapListEntry    : _SINGLE_LIST_ENTRY
   +0x0b0 Queue            : Ptr64 _KQUEUE
   +0x0b8 Teb              : Ptr64 Void
   +0x0c0 Timer            : _KTIMER
   +0x100 AutoAlignment    : Pos 0, 1 Bit
   +0x100 DisableBoost     : Pos 1, 1 Bit
   +0x100 EtwStackTraceApc1Inserted : Pos 2, 1 Bit
   +0x100 EtwStackTraceApc2Inserted : Pos 3, 1 Bit
   +0x100 CalloutActive    : Pos 4, 1 Bit
   +0x100 ApcQueueable     : Pos 5, 1 Bit
   +0x100 EnableStackSwap  : Pos 6, 1 Bit
   +0x100 GuiThread        : Pos 7, 1 Bit
   +0x100 UmsPerformingSyscall : Pos 8, 1 Bit
   +0x100 VdmSafe          : Pos 9, 1 Bit
   +0x100 UmsDispatched    : Pos 10, 1 Bit
   +0x100 ReservedFlags    : Pos 11, 21 Bits
   +0x100 ThreadFlags      : Int4B
   +0x104 Spare0           : Uint4B
   +0x108 WaitBlock        : [4] _KWAIT_BLOCK
   +0x108 WaitBlockFill4   : [44] UChar
   +0x134 ContextSwitches  : Uint4B
   +0x108 WaitBlockFill5   : [92] UChar
   +0x164 State            : UChar
   +0x165 NpxState         : Char
   +0x166 WaitIrql         : UChar
   +0x167 WaitMode         : Char
   +0x108 WaitBlockFill6   : [140] UChar
   +0x194 WaitTime         : Uint4B
   +0x108 WaitBlockFill7   : [168] UChar
   +0x1b0 TebMappedLowVa   : Ptr64 Void
   +0x1b8 Ucb              : Ptr64 _UMS_CONTROL_BLOCK
   +0x108 WaitBlockFill8   : [188] UChar
   +0x1c4 KernelApcDisable : Int2B
   +0x1c6 SpecialApcDisable : Int2B
   +0x1c4 CombinedApcDisable : Uint4B
   +0x1c8 QueueListEntry   : _LIST_ENTRY
   +0x1d8 TrapFrame        : Ptr64 _KTRAP_FRAME
   +0x1e0 FirstArgument    : Ptr64 Void
   +0x1e8 CallbackStack    : Ptr64 Void
   +0x1e8 CallbackDepth    : Uint8B
   +0x1f0 ApcStateIndex    : UChar
   +0x1f1 BasePriority     : Char
   +0x1f2 PriorityDecrement : Char
   +0x1f2 ForegroundBoost  : Pos 0, 4 Bits
   +0x1f2 UnusualBoost     : Pos 4, 4 Bits
   +0x1f3 Preempted        : UChar
   +0x1f4 AdjustReason     : UChar
   +0x1f5 AdjustIncrement  : Char
   +0x1f6 PreviousMode     : Char
   +0x1f7 Saturation       : Char
   +0x1f8 SystemCallNumber : Uint4B
   +0x1fc FreezeCount      : Uint4B
   +0x200 UserAffinity     : _GROUP_AFFINITY
   +0x210 Process          : Ptr64 _KPROCESS
   +0x218 Affinity         : _GROUP_AFFINITY
   +0x228 IdealProcessor   : Uint4B
   +0x22c UserIdealProcessor : Uint4B
   +0x230 ApcStatePointer  : [2] Ptr64 _KAPC_STATE
   +0x240 SavedApcState    : _KAPC_STATE
   +0x240 SavedApcStateFill : [43] UChar
   +0x26b WaitReason       : UChar
   +0x26c SuspendCount     : Char
   +0x26d Spare1           : Char
   +0x26e CodePatchInProgress : UChar
   +0x270 Win32Thread      : Ptr64 Void
   +0x278 StackBase        : Ptr64 Void
   +0x280 SuspendApc       : _KAPC
   +0x280 SuspendApcFill0  : [1] UChar
   +0x281 ResourceIndex    : UChar
   +0x280 SuspendApcFill1  : [3] UChar
   +0x283 QuantumReset     : UChar
   +0x280 SuspendApcFill2  : [4] UChar
   +0x284 KernelTime       : Uint4B
   +0x280 SuspendApcFill3  : [64] UChar
   +0x2c0 WaitPrcb         : Ptr64 _KPRCB
   +0x280 SuspendApcFill4  : [72] UChar
   +0x2c8 LegoData         : Ptr64 Void
   +0x280 SuspendApcFill5  : [83] UChar
   +0x2d3 LargeStack       : UChar
   +0x2d4 UserTime         : Uint4B
   +0x2d8 SuspendSemaphore : _KSEMAPHORE
   +0x2d8 SuspendSemaphorefill : [28] UChar
   +0x2f4 SListFaultCount  : Uint4B
   +0x2f8 ThreadListEntry  : _LIST_ENTRY
   +0x308 MutantListHead   : _LIST_ENTRY
   +0x318 SListFaultAddress : Ptr64 Void
   +0x320 ReadOperationCount : Int8B
   +0x328 WriteOperationCount : Int8B
   +0x330 OtherOperationCount : Int8B
   +0x338 ReadTransferCount : Int8B
   +0x340 WriteTransferCount : Int8B
   +0x348 OtherTransferCount : Int8B
   +0x350 ThreadCounters   : Ptr64 _KTHREAD_COUNTERS
   +0x358 XStateSave       : Ptr64 _XSTATE_SAVE

每个KPROCESS都代表一个进程。ActiveProcessors记录下了当前进程正在哪些处理器上运行。+0x070 ReadyListHead    : _LIST_ENTRY 代表了双向链表的标头,该链表记录了这个进程中处于就绪状态但尚未被加入全局就绪链表的线程。该链表每一项都是一个指向KTHREAD对象WaitListEntry域的地址。KPROCESS对象中记录的信息主要包括两类:一类跟进程的内存环境相关,比如页目录表,交换状态。另一类是与其线程相关的一些属性,比如线程列表以及线程所需要的优先级、时限设置。


在KTHREAD中我们看到Teb域 +0x0b8 Teb              : Ptr64 Void,TEB指向进程空间中的一个TEB(线程环境块结构)。TrapFrame域是最重要的部分,它表示当一个线程离开运行状态时,其当前的执行状态,比如现在的指令IP在哪里,各个寄存器中的值是什么,都必须保留下来,以便下次再轮到这个线程运行时,可以恢复原来的执行状态。TrapFrame是记录控制流状态的数据结构,它是一个指向KTRAP_FRAME类型的指针。


通过KPROCESS和KTHREAD我们看到,内核层的进程和线程对象只包含了系统资源管理和多控制流并发执行所涉及的基本信息,没有包含与应用程序相关联的信息。进程对象提供了线程的基本执行环境,包括进程地址空间和一组进程范围内公用的参数;线程对象提供了为参与线程调度而必须的各种信息及其维护控制流的状态。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值