Inside Microsoft Windows 2000

Inside Microsoft Windows 2000

by David A. Solomon, Mark E. Russinovich, Mark Russinovich

This newly updated, official guide to the Microsoft "RM" Windows 2000 core architecture and internals provides the key to help readers unlock the full power of Microsoft's premier operating system. Written in full partnership with the Microsoft Windows 2000 product development team, this book takes developers, technical managers, and IS professionals deep

…  See more details below


This newly updated, official guide to the Microsoft "RM" Windows 2000 core architecture and internals provides the key to help readers unlock the full power of Microsoft's premier operating system. Written in full partnership with the Microsoft Windows 2000 product development team, this book takes developers, technical managers, and IS professionals deep into the core components of Windows 2000. Along the way, it provides abundant information and perspective that readers can quickly apply for better design, debugging, performance, and troubleshooting. It's packed with up-to-the-minute information — and unrivaled programming insights — about topics such as Plug and Play, power management, the Windows Driver Model, security, 64-bit extended addressing support, job objects, new priority classes, NTFS extensions, kernel streaming and kernel code, and registry internals. In short, this is the must-have text for anyone who wants to get the most out of Microsoft Windows 2000.

Read More

Product Details

Microsoft Press
Publication date:
DV-MPS Inside
Edition description:
3rd ed.
Product dimensions:
7.61(w) x 9.55(h) x 1.85(d)

Read an Excerpt

Chapter 6: Processes, Threads, and Jobs

In this chapter, we'll explain the data structures and algorithms that deal with processes, threads, and jobs in Microsoft Windows 2000. The first section focuses on the internal structures that make up a process. The second section outlines the steps involved in creating a process (and its initial thread). The internals of threads and thread scheduling are then described. The chapter concludes with a description of the job object.

Where relevant performance counters or kernel variables exist, they are mentioned. Although this book isn't a Win32 programming book, the pertinent process, thread, and job Win32 functions are listed so that you can pursue additional information on their use.

Because processes and threads touch so many components in Windows 2000, a number of terms and data structures (such as working sets, objects and handles, system memory heaps, and so on) are referred to in this chapter but are explained in detail elsewhere in the book. To fully understand this chapter, you need to be familiar with the terms and concepts explained in chapters 1 and 2, such as the difference between a process and a thread, the Windows 2000 virtual address space layout, and the difference between user mode and kernel mode.

Process Internals

This section describes the key Windows 2000 process data structures. Also listed are key kernel variables, performance counters, and functions and tools that relate to processes.

Data Structures

Each Windows 2000 process is represented by an executive process (EPROCESS) block. Besides containing many attributes relating to a process, anEPROCESS block contains and points to a number of other related data structures. For example, each process has one or more threads represented by executive thread (ETHREAD) blocks. (Thread data structures are explained in the section "Thread Internals" later in this chapter.) The EPROCESS block and its related data structures exist in system space, with the exception of the process environment block (PEB), which exists in the process address space (because it contains information that is modified by user-mode code).

In addition to the EPROCESS block, the Win32 subsystem process (Csrss) maintains a parallel structure for each Windows 2000 process that executes a Win32 program. Also, the kernel-mode part of the Win32 subsystem (Win32k.sys) has a per-process data structure that is created the first time a thread calls a Win32 USER or GDI function that is implemented in kernel mode.

Figure 6-1 is a simplified diagram of the process and thread data structures. Each data structure shown in the figure is described in detail in this chapter....

Click to view graphic

Figure 6-1 Data structures associated with processes and threads

First let's focus on the process block. (We'll get to the thread block in the section "Thread Internals" later in the chapter.) Figure 6-2 shows the key fields in an EPROCESS block....

Click to view graphic

Figure 6-2 Structure of an executive process block


Displaying the Format of an EPROCESS Block

For a list of most of the fields that make up an EPROCESS block and their offsets in hexadecimal, type !processfields in the kernel debugger. (See Chapter 1 for more information on the kernel debugger.) The output looks like this:

kd> !processfields EPROCESS structure offsets:    Pcb:                               0x0    ExitStatus:                        0x6c    LockEvent:                         0x70    LockCount:                         0x80    CreateTime:                        0x88    ExitTime:                          0x90    LockOwner:                         0x98    UniqueProcessId:                   0x9c    ActiveProcessLinks:                0xa0    QuotaPeakPoolUsage[0]:             0xa8    QuotaPoolUsage[0]:                 0xb0    PagefileUsage:                     0xb8    CommitCharge:                      0xbc    PeakPagefileUsage:                 0xc0    PeakVirtualSize:                   0xc4    VirtualSize:                       0xc8    Vm:                                0xd0    DebugPort:                         0x120    ExceptionPort:                     0x124    ObjectTable:                       0x128    Token:                             0x12c    WorkingSetLock:                    0x130    WorkingSetPage:                    0x150    ProcessOutswapEnabled:             0x154    ProcessOutswapped:                 0x155    AddressSpaceInitialized:           0x156    AddressSpaceDeleted:               0x157    AddressCreationLock:               0x158    ForkInProgress:                    0x17c    VmOperation:                       0x180    VmOperationEvent:                  0x184    PageDirectoryPte:                  0x1f0    LastFaultCount:                    0x18c    VadRoot:                           0x194    VadHint:                           0x198    CloneRoot:                         0x19c    NumberOfPrivatePages:              0x1a0  NumberOfLockedPages:               0x1a4    ForkWasSuccessful:                 0x182    ExitProcessCalled:                 0x1aa    CreateProcessReported:             0x1ab    SectionHandle:                     0x1ac    Peb:                               0x1b0    SectionBaseAddress:                0x1b4    QuotaBlock:                        0x1b8    LastThreadExitStatus:              0x1bc    WorkingSetWatch:                   0x1c0    InheritedFromUniqueProcessId:      0x1c8    GrantedAccess:                     0x1cc    DefaultHardErrorProcessing         0x1d0    LdtInformation:                    0x1d4    VadFreeHint:                       0x1d8    VdmObjects:                        0x1dc    DeviceMap:                         0x1e0    ImageFileName[0]:                  0x1fc    VmTrimFaultValue:                  0x20c    Win32Process:                      0x214    Win32WindowStation:                0x1c4

The !processfields command shows the format of a process block, not its contents. (The !process command actually dumps the contents of a process block. An annotated example of the output from this command is included later in this section.) Although some of the field names are self-explanatory, the output doesn't give the data type of the fields, nor does it show the format of the structures that are included within or pointed to by the EPROCESS block, such as the kernel process block (Pcb), quota block (QuotaBlock), and so on. By examining the offsets, however, you can at least tell the length of a field. (Hint: Fields that are 4 bytes long and refer to some other structure are likely pointers.)

You can also use the !strct command (in the secondary kernel debugger extension library Kdex2x86.dll) to display the format of a process block. This command displays every field and its database (whereas the !processfields command displays only some of the fields and doesn't display data type information). A portion of the output follows:

kd> !kdex2x86.strct eprocessLoaded kdex2x86 extension DLLstruct   _EPROCESS (sizeof=648)+000 struct   _KPROCESS Pcb+000    struct   _DISPATCHER_HEADER Header+000       byte     Type+001       byte     Absolute+002       byte     Size+003       byte     Inserted+004       int32    SignalState+008       struct   _LIST_ENTRY WaitListHead+008          struct   _LIST_ENTRY *Flink+00c          struct   _LIST_ENTRY *Blink+010    struct   _LIST_ENTRY ProfileListHead+010       struct   _LIST_ENTRY *Flink+014       struct   _LIST_ENTRY *Blink+018    uint32   DirectoryTableBase[2]+020    struct   _KGDTENTRY LdtDescriptor+020       uint16   LimitLow+022       uint16   BaseLow+024       union    __unnamed9 HighWord+024          struct   __unnamed10 Bytes+024             byte     BaseMid+025             byte     Flags1+026             byte     Flags2+027             byte     BaseHi+024          struct   __unnamed11 Bits+024             bits0-7 BaseMid+024             bits8-12 Type+024             bits13-14 Dpl+024             bits15-15 Pres+024             bits16-19 LimitHi+024             bits20-20 Sys+024             bits21-21 Reserved_0+024             bits22-22 Default_Big+024             bits23-23 Granularity+024             bits24-31 BaseHi+028    struct   _KIDTENTRY Int21Descriptor+028       uint16   Offset+02a       uint16   Selector+02c       uint16   Access+02e       uint16   ExtendedOffset+030 uint16   IopmOffset+032    byte     Iopl+033    byte     VdmFlag+034    uint32   ActiveProcessors+038    uint32   KernelTime+03c    uint32   UserTime+040    struct   _LIST_ENTRY ReadyListHead+040       struct   _LIST_ENTRY *Flink+044       struct   _LIST_ENTRY *Blink+048    struct   _LIST_ENTRY SwapListEntry+048       struct   _LIST_ENTRY *Flink+04c       struct   _LIST_ENTRY *Blink+050    struct   _LIST_ENTRY ThreadListHead+050       struct   _LIST_ENTRY *Flink+054       struct   _LIST_ENTRY *Blink+058    uint32   ProcessLock+05c    uint32   Affinity+060    uint16   StackCount+062    char     BasePriority+063    char     ThreadQuantum+064    byte     AutoAlignment+065    byte     State+066    byte     ThreadSeed+067    byte     DisableBoost+068    byte     PowerState+069    byte     DisableQuantum+06a    byte     Spare[2]+06c int32    ExitStatus+070 struct   _KEVENT LockEvent+070    struct   _DISPATCHER_HEADER Header+070       byte     Type+071       byte     Absolute+072       byte     Size+073       byte     Inserted+074       int32    SignalState+078       struct   _LIST_ENTRY WaitListHead+078          struct   _LIST_ENTRY *Flink+07c          struct   _LIST_ENTRY *Blink+080 uint32   LockCount+088 union    _LARGE_INTEGER CreateTime+088    uint32   LowPart+08c    int32    HighPart+088    struct   __unnamed3 u+088       uint32   LowPart+08c       int32    HighPart+088    int64    QuadPart+090 union    _LARGE_INTEGER ExitTime+090    uint32   LowPart+094    int32    HighPart+090    struct   __unnamed3 u+090       uint32   LowPart+094       int32    HighPart+090    int64    QuadPart+098 struct   _KTHREAD *LockOwner+09c void     *UniqueProcessId+0a0 struct   _LIST_ENTRY ActiveProcessLinks+0a0 struct   _LIST_ENTRY *Flink+0a4    struct   _LIST_ENTRY *Blink+0a8 uint32   QuotaPeakPoolUsage[2]+0b0 uint32   QuotaPoolUsage[2]+0b8 uint32   PagefileUsage+0bc uint32   CommitCharge+0c0 uint32   PeakPagefileUsage+0c4 uint32   PeakVirtualSize+0c8 uint32   VirtualSize+0d0 struct   _MMSUPPORT Vm+0d0    union    _LARGE_INTEGER LastTrimTime+0d0       uint32   LowPart+0d4       int32    HighPart+0d0       struct   __unnamed3 u+0d0          uint32   LowPart+0d4          int32    HighPart+0d0       int64    QuadPart+0d8    uint32   LastTrimFaultCount+0dc    uint32   PageFaultCount+0e0    uint32   PeakWorkingSetSize+0e4    uint32   WorkingSetSize+0e8    uint32   MinimumWorkingSetSize+0ec    uint32   MaximumWorkingSetSize+0f0     *VmWorkingSetList+0f4    struct   _LIST_ENTRY WorkingSetExpansionLinks+0f4       struct   _LIST_ENTRY *Flink+0f8       struct   _LIST_ENTRY *Blink+0fc    byte     AllowWorkingSetAdjustment+0fd    byte     AddressSpaceBeingDeleted+0fe    byte     ForegroundSwitchCount+0ff    byte     MemoryPriority+100    union    __unnamed13 u+100       uint32   LongFlags+100       struct   _MMSUPPORT_FLAGS Flags+100          bits0-0 SessionSpace+100          bits1-1 BeingTrimmed+100          bits2-2 ProcessInSession+100          bits3-3 SessionLeader+100          bits4-4 TrimHard+100          bits5-5 WorkingSetHard+100          bits6-6 WriteWatch+100          bits7-31 Filler+104    uint32   Claim+108    uint32   NextEstimationSlot+10c    uint32   NextAgingSlot+110    uint32   EstimatedAvailable+114    uint32   GrowthSinceLastEstimate+118 struct   _LIST_ENTRY SessionProcessLinks+118    struct   _LIST_ENTRY *Flink+11c    struct   _LIST_ENTRY *Blink+120 void     *DebugPort+124 void *ExceptionPort+128 struct   _HANDLE_TABLE *ObjectTable+12c void     *Token+130 struct   _FAST_MUTEX WorkingSetLock+130    int32    Count+134    struct   _KTHREAD *Owner+138    uint32   Contention+13c    struct   _KEVENT Event+13c       struct   _DISPATCHER_HEADER Header+13c          byte     Type+13d          byte     Absolute+13e          byte     Size+13f          byte     Inserted+140          int32    SignalState+144          struct   _LIST_ENTRY WaitListHead+144             struct   _LIST_ENTRY *Flink+148             struct   _LIST_ENTRY *Blink+14c    uint32   OldIrql+150 uint32   WorkingSetPage+154 byte     ProcessOutswapEnabled+155 byte     ProcessOutswapped+156 byte     AddressSpaceInitialized+157 byte     AddressSpaceDeleted+158 struct   _FAST_MUTEX AddressCreationLock+158    int32    Count+15c    struct   _KTHREAD *Owner+160    uint32   Contention+164    struct   _KEVENT Event+164       struct   _DISPATCHER_HEADER Header+164          byte     Type+165          byte     Absolute+166          byte     Size+167          byte     Inserted+168          int32    SignalState+16c          struct   _LIST_ENTRY WaitListHead+16c             struct   _LIST_ENTRY *Flink+170             struct   _LIST_ENTRY *Blink+174    uint32   OldIrql+178 uint32   HyperSpaceLock+17c struct   _ETHREAD *ForkInProgress+180 uint16   VmOperation+182 byte     ForkWasSuccessful+183 byte     MmAgressiveWsTrimMask+184 struct   _KEVENT *VmOperationEvent+188 void     *PaeTop+18c uint32   LastFaultCount+190 uint32   ModifiedPageCount+194 void     *VadRoot+198 void     *VadHint+19c void     *CloneRoot+1a0 uint32   NumberOfPrivatePages+1a4 uint32   NumberOfLockedPages+1a8 uint16   NextPageColor+1aa byte     ExitProcessCalled+1ab byte     CreateProcessReported+1ac void     *SectionHandle+1b0 struct   _PEB *Peb+1b4 void     *SectionBaseAddress+1b8 struct   _EPROCESS_QUOTA_BLOCK *QuotaBlock+1bc int32    LastThreadExitStatus+1c0 struct   _PAGEFAULT_HISTORY *WorkingSetWatch+1c4 void     *Win32WindowStation+1c8 void     *InheritedFromUniqueProcessId+1cc uint32   GrantedAccess+1d0 uint32   DefaultHardErrorProcessing+1d4 void     *LdtInformation+1d8 void     *VadFreeHint+1dc void     *VdmObjects+1e0 void     *DeviceMap+1e4 uint32   SessionId+1e8 struct   _LIST_ENTRY PhysicalVadList+1e8    struct   _LIST_ENTRY *Flink+1ec    struct   _LIST_ENTRY *Blink+1f0 struct   _HARDWARE_PTE_X86 PageDirectoryPte+1f0    bits0-0 Valid+1f0    bits1-1 Write+1f0    bits2-2 Owner+1f0    bits3-3 WriteThrough+1f0    bits4-4 CacheDisable+1f0    bits5-5 Accessed+1f0    bits6-6 Dirty+1f0    bits7-7 LargePage+1f0    bits8-8 Global+1f0    bits9-9 CopyOnWrite+1f0    bits10-10 Prototype+1f0    bits11-11 reserved+1f0    bits12-31 PageFrameNumber+1f0 uint64   Filler+1f8 uint32   PaePageDirectoryPage+1fc byte     ImageFileName[16]+20c uint32   VmTrimFaultValue+210 byte     SetTimerResolution+211 byte     PriorityClass+212 byte     SubSystemMinorVersion+213 byte     SubSystemMajorVersion+212 uint16   SubSystemVersion+214 void     *Win32Process+218 struct   _EJOB *Job+21c uint32   JobStatus+220 struct   _LIST_ENTRY JobLinks+220    struct   _LIST_ENTRY *Flink+224    struct   _LIST_ENTRY *Blink+228 void     *LockedPagesList+22c void     *SecurityPort+230 struct   _WOW64_PROCESS *Wow64Process+238 union    _LARGE_INTEGER ReadOperationCount+238    uint32   LowPart+23c    int32    HighPart+238    struct   __unnamed3 u+238       uint32   LowPart+23c       int32 HighPart+238    int64    QuadPart+240 union    _LARGE_INTEGER WriteOperationCount+240    uint32   LowPart+244    int32    HighPart+240    struct   __unnamed3 u+240       uint32   LowPart+244       int32    HighPart+240    int64    QuadPart+248 union    _LARGE_INTEGER OtherOperationCount+248    uint32   LowPart+24c    int32    HighPart+248    struct   __unnamed3 u+248       uint32   LowPart+24c       int32    HighPart+248    int64    QuadPart+250 union    _LARGE_INTEGER ReadTransferCount+250    uint32   LowPart+254    int32    HighPart+250    struct   __unnamed3 u+250       uint32   LowPart+254       int32    HighPart+250    int64    QuadPart+258 union    _LARGE_INTEGER WriteTransferCount+258    uint32   LowPart+25c    int32    HighPart+258    struct   __unnamed3 u+258       uint32   LowPart+25c       int32    HighPart+258    int64    QuadPart+260 union    _LARGE_INTEGER OtherTransferCount+260    uint32   LowPart+264    int32    HighPart+260    struct   __unnamed3 u+260       uint32   LowPart+264       int32    HighPart+260    int64    QuadPart+268 uint32   CommitChargeLimit+26c uint32   CommitChargePeak+270 struct   _LIST_ENTRY ThreadListHead+270    struct   _LIST_ENTRY *Flink+274    struct   _LIST_ENTRY *Blink+278 struct   _RTL_BITMAP *VadPhysicalPagesBitMap+27c uint32   VadPhysicalPages+280 uint32   AweLock

Table 6-1 explains some of the fields in the preceding experiment in more detail and includes references to other places in the book where you can find more information about them. As we've said before and will no doubt say again, processes and threads are such an integral part of Windows 2000 that it's impossible to talk about them without referring to many other parts of the system. To keep the length of this chapter manageable, however, we've covered those related subjects (such as memory management, security, objects, and handles) elsewhere....

Read More

Meet the Author

David A. Solomon, president of David Solomon Expert Seminars, Inc. (, teaches Windows 2000 internals to leading corporations worldwide. Previously, he was a lead developer on the VMS operating system at Digital Equipment Corporation.

Mark E. Russinovich is the author of the Sysinternals Web site ( and cofounder and chief software architect of Winternals Software (, specializing in advanced systems tools for Windows 2000. He writes the "Internals" column in Windows 2000 Magazine. Formerly at IBM Research, Mark holds a Ph.D. in computer engineering from Carnegie Mellon University.

Customer Reviews

Average Review:

Write a Review

and post it to your social network


Most Helpful Customer Reviews

See all customer reviews >