Debugging Tools for Windows

!process

!process扩展显示指定的进程或所有进程的信息,包括EPROCESS块在内。

该命令只能在内核模式调试时使用。

语法

Windows 2000的语法:

!process [/s Session] [Process [Flags]] 
!process [/s Session0 Flags ImageName 

Windows XP和之后的语法:

!process [/s Session] [/Module] [Process [Flags]] 
!process [/s Session] [/Module0 Flags ImageName 

参数

/s Session
指定拥有给定进程的会话(session)。
/m Module
(Windows XP和之后) 指定拥有需要的进程的模块。
Process
指定目标机上某个进程的16进制地址或者进程ID。

Process的值决定了!process命令显示的是进程地址还是进程ID。如果在任何系统中省略掉Process,调试器只显示当前系统进程的数据。如果Process0并且省略ImageName,调试器显示所有活动进程的信息。

Flags
指定显示内容的级别。Flags可以是下面这些位的任意组合。如果Flags为0,只会显示很少的信息。默认值根据Windows版本和Process的值会有所不同。默认值根据Windows版本和Process的不同会有所不同。在Windows 2000中,当Process省略,或者Process为0并且省略ImageFile时,默认值是0x3;否则默认值为0xF。在Windows XP和之后,当Process省略或者为0或-1时,默认值为0x3,否则为0xF。
Bit 0 (0x1)
显示时间和优先级统计。
Bit 1 (0x2)
显示该进程关联的线程和事件列表,以及它们的等待状态。
Bit 2 (0x4)
显示进程关联的线程列表。如果没有同时指定Bit 1(0x2),则每个线程显示在单独一行上。如果同时指定了Bit 1,则每个线程还会显示堆栈回溯。
Bit 3 (0x8)
(Windows XP和之后) 显示每个函数的返回地址、堆栈指针,以及(在Itanium系统上)bsp寄存器的值。不显示函数的参数。
Bit 4 (0x10)
(Windows XP和之后) 在命令执行期间将进程上下文设定为指定的进程。这样会使得线程调用堆栈显示更加精确。因为该标志相当于对这个进程使用了.process /p /r,会丢弃(discard)任何存在的用户模式模块列表。当Process为0时,调试器显示所有进程,并且显示每一个时都会切换进程上下文。如果只显示单个进程,并且它的用户模式状态已经被刷新(例如,使用了.process /p /r),那么就不需要使用这个标志。该标志仅在使用了 Bit 0(0x1)的时候起效。
ImageName
指定要显示的进程的名字。调试器会显示所有可执行映像名和ImageName匹配的进程。映像名必须匹配EPROCESS 块中的那个。一般来说,这是启动了该进程的可执行文件的名字,包含扩展名(一般是.exe),并且第15个字符之后的字符被裁减掉。不能指定包含空格的映像名。指定了ImageName 时,Process必须为0。

DLL

Windows 2000 Kdextx86.dll
Windows XP和之后 Kdexts.dll

注释

下面是!process 0 0的显示的示例:

kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
PROCESS 80a02a60  Cid: 0002    Peb: 00000000  ParentCid: 0000
    DirBase: 00006e05  ObjectTable: 80a03788  TableSize: 150.
    Image: System
PROCESS 80986f40  Cid: 0012    Peb: 7ffde000  ParentCid: 0002
    DirBase: 000bd605  ObjectTable: 8098fce8  TableSize:  38.
    Image: smss.exe
PROCESS 80958020  Cid: 001a    Peb: 7ffde000  ParentCid: 0012
    DirBase: 0008b205  ObjectTable: 809782a8  TableSize: 150.
    Image: csrss.exe
PROCESS 80955040  Cid: 0020    Peb: 7ffde000  ParentCid: 0012
    DirBase: 00112005  ObjectTable: 80955ce8  TableSize:  54.
    Image: winlogon.exe
PROCESS 8094fce0  Cid: 0026    Peb: 7ffde000  ParentCid: 0020
    DirBase: 00055005  ObjectTable: 80950cc8  TableSize: 222.
    Image: services.exe
PROCESS 8094c020  Cid: 0029    Peb: 7ffde000  ParentCid: 0020
    DirBase: 000c4605  ObjectTable: 80990fe8  TableSize: 110.
    Image: lsass.exe
PROCESS 809258e0  Cid: 0044    Peb: 7ffde000  ParentCid: 0026
    DirBase: 001e5405  ObjectTable: 80925c68  TableSize:  70.
    Image: SPOOLSS.EXE

这个表格是!process 0 0输出中出现的各个部分的说明。

成员 含义
Process address 单词PROCESS之后的8字符长度的16进制数字是EPROCESS块的地址。上面例子中最后一条的进程地址为0x809258E0。
Process ID (PID) Cid后的16进制数字。上面例子中最后一条的PID是0x44,或者10进制的68。
Process Environment Block (PEB) Peb后面的16进制数字是进程环境块的地址 。上面例中最后一条的PEB位于0x7FFDE000。
Parent process PID ParentCid后面的16进制数字是父进程的PID。上面例中最后一条的父进程PID为0x26,或者10进制的38。
Image 拥有该进程的模块名。上例中最后一条的所有者为spoolss.exe。第一条的所有者为操作系统本身。
Process object address ObjectTable后的16进制数字。上例最后一条中,进程对象(process object)地址为0x80925c68。

要显示某个进程的完整信息,可以将Flags设置为7。可以将Process设置为进程地址、进程ID,或者将ImageName设置为可执行映像的名字来指定进程。例如:

kd> !process fb667a00 7
PROCESS fb667a00 Cid: 0002  Peb: 00000000 ParentCid: 0000
  DirBase: 00030000 ObjectTable: e1000f88 TableSize: 112.
  Image: System
  VadRoot fb666388 Clone 0 Private 4. Modified 9850. Locked 0.
  FB667BBC MutantState Signalled OwningThread 0
  Token               e10008f0
  ElapsedTime            15:06:36.0338
  UserTime             0:00:00.0000
  KernelTime            0:00:54.0818
  QuotaPoolUsage[PagedPool]     1480
Working Set Sizes (now,min,max) (3, 50, 345)
  PeakWorkingSetSize        118
  VirtualSize            1 Mb
  PeakVirtualSize          1 Mb
  PageFaultCount          992
  MemoryPriority          BACKGROUND
  BasePriority           8
  CommitCharge           8

    THREAD fb667780 Cid 2.1 Teb: 00000000 Win32Thread: 80144900 WAIT: (WrFreePage) KernelMode Non-Alertable
    80144fc0 SynchronizationEvent
    Not impersonating
    Owning Process fb667a00
    WaitTime (seconds)   32278
    Context Switch Count  787
    UserTime         0:00:00.0000
    KernelTime        0:00:21.0821
    Start Address Phase1Initialization (0x801aab44)
    Initial Sp fb26f000 Current Sp fb26ed00
    Priority 0 BasePriority 0 PriorityDecrement 0 DecrementCount 0

    ChildEBP RetAddr Args to Child
    fb26ed18 80118efc c0502000 804044b0 00000000 KiSwapThread+0xb5
    fb26ed3c 801289d9 80144fc0 00000008 00000000 KeWaitForSingleObject+0x1c2

注意输出中的进程对象的地址可以用于类似!handle这样的其他扩展命令,用于获得更多信息。

下面表格用于说明前面例子中的各个部分。

成员 含义
WAIT 这个头后面附加的注释说明了等待原因。使用命令dt nt!_KWAIT_REASON可以显示所有等待原因的列表。
ElapsedTime 列出从进程创建以来经过了多长时间。显示是以Hours : Minutes : Seconds . Milliseconds格式的。
UserTime 显示进程在用户模式下执行的时间。如果UserTime特别高,可能说明了这个进程正在消耗系统资源。显示格式和ElapsedTime一样。
KernelTime 显示进程在内核模式下运行的时间。如果KernelTime的值非常高,可能意味着该进程在消耗系统资源。显示格式和ElapsedTime一样。
Working Set sizes 显示进程当前的最小和最大工作集(working set)大小,以页面数为单位。如果工作集异常的大,说明进程可能存在内存泄露,或者消耗了很多系统资源。
QuotaPoolUsage entries 列出进程使用的分页和非分页内存池。对存在内存泄露的系统,查看所有进程额外的非分页内存使用可以知道哪个进程存在内存泄露。
Clone 指示进程是否是由POSIX 或Interix子系统创建的。
Private 指示进程当前使用到的私有(非共享)页面数量。包括物理内存中的和已经换出的内存。

除了进程信息之外,线程信息中还包含被线程锁定的资源列表。这个信息位于线程信息的第三行。上面例子中,线程锁定了一个位于80144fc0处的SynchronizationEvent资源。通过将该地址和!kdext*.locks扩展命令显示的锁的列表对比,可以知道哪个进程拥有资源的排它锁(exclusive lock)。

!stacks扩展给出每个线程的状态的简单摘要。它可以代替!process用于对系统进行快速的查看,特别是调试像资源争用或者死锁这样的多线程问题时。

附加信息

关于内核模式下进程的信息,查看改变上下文。关于对进程和线程进行分析的信息,查看Mark Russinovich 和David Solomon 编写的Microsoft Windows Internals

Build machine: CAPEBUILD