windbg-!process显示进程

本文介绍如何使用Windbg命令!process来查看系统中进程的信息,包括显示所有进程、指定进程详细信息及通过进程名查找进程的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

!process 0 0 显示进程列表:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. kd> !process 0 0  
  2. **** NT ACTIVE PROCESS DUMP ****  
  3. PROCESS 825b7830  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000  
  4.     DirBase: 02b40020  ObjectTable: e1003e00  HandleCount: 254.  
  5.     Image: System  
  6.   
  7. PROCESS 8241d490  SessionId: none  Cid: 0178    Peb: 7ffdf000  ParentCid: 0004  
  8.     DirBase: 02b40040  ObjectTable: e148a4a0  HandleCount:  19.  
  9.     Image: smss.exe  
  10.   
  11. PROCESS 824d6268  SessionId: 0  Cid: 0264    Peb: 7ffd4000  ParentCid: 0178  
  12.     DirBase: 02b40060  ObjectTable: e148fa18  HandleCount: 383.  
  13.     Image: csrss.exe  
  14. ....  
!process XXX显示指定进程的所有信息, !process XXX 0显示指定进程的基本信息

XXX可以为EPROCESS或进程ID

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. kd> !process @$proc 0  
  2. PROCESS 825b7830  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000  
  3.     DirBase: 02b40020  ObjectTable: e1003e00  HandleCount: 254.  
  4.     Image: System  
  5.   
  6. kd> !process 4 0  
  7. Searching for Process with Cid == 4  
  8. Cid Handle table at e1005000 with 366 Entries in use  
  9. PROCESS 825b7830  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000  
  10.     DirBase: 02b40020  ObjectTable: e1003e00  HandleCount: 254.  
  11.     Image: System  
!process 0 0 XXX.exe查找进程

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. kd> !process 0 0  smss.exe  
  2. PROCESS 8241d490  SessionId: none  Cid: 0178    Peb: 7ffdf000  ParentCid: 0004  
  3.     DirBase: 02b40040  ObjectTable: e148a4a0  HandleCount:  19.  
  4.     Image: smss.exe  
  5.   
  6. kd> !process 0 0 system  
  7. PROCESS 825b7830  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000  
  8.     DirBase: 02b40020  ObjectTable: e1003e00  HandleCount: 254.  
  9.     Image: System  

注意只有sytem,没有sytem.exe!!!

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. kd> !process 0 0 system.exe  

上述命令是找不到的


<think>我们被要求使用WinDbg中的!handle命令来排查CloseHandle调用缓慢的问题。根据引用[1]中提到,WinDbg!handle命令可以列出当前进程的所有句柄,这有助于我们分析句柄的状态。在CloseHandle调用缓慢的场景中,我们主要关注两个方面:1.句柄的引用计数:如果句柄被多次复制(例如通过DuplicateHandle),那么CloseHandle需要等待所有引用都被关闭才会真正释放内核对象。2.句柄关联的未完成I/O操作:例如文件或套接字句柄,如果有未完成的异步I/O,CloseHandle会等待这些操作完成(或可取消的情况下被取消)才会返回。使用WinDbg!handle命令可以查看句柄的详细信息,包括其引用计数和对象类型。以下是具体步骤:步骤1:附加到目标进程WinDbg中,通过File>AttachtoProcess附加到出现CloseHandle缓慢的进程。步骤2:使用!handle命令查看所有句柄的摘要输入命令:!handle00这个命令会列出当前进程的所有句柄,包括句柄值、类型和对象地址。步骤3:找到导致问题的句柄根据步骤2的输出,我们可以关注那些数量异常多的对象类型(比如文件、事件、线程等),或者根据程序逻辑找到可能被频繁操作的对象。步骤4:查看特定句柄的详细信息如果我们怀疑某个句柄(例如句柄值为0x1c)有问题,可以输入:!handle0x1cf这里的'f'表示显示详细信息。在详细信息中,我们可以查看:-对象类型(如File,Event,Thread等)-引用计数(ReferenceCount)-对于文件对象,可能还会显示当前未完成的I/O数量(如果有的话)步骤5:分析引用计数高的原因如果发现某个句柄的引用计数很高(比如远大于1),说明可能有其他线程或进程(通过DuplicateHandle)还在使用这个对象。我们需要检查代码中是否有地方复制了句柄但没有关闭。步骤6:检查未完成的I/O对于文件、管道、套接字等句柄,如果CloseHandle卡住,很可能是由于未完成的I/O操作。在!handle的详细输出中,不一定直接显示未完成I/O的数量,但我们可以通过以下方法:-使用!objref命令查看对象引用链(但需要先获取对象地址)-使用!irp命令查看挂起的IRP(需要知道驱动相关知识)另一种思路:使用ProcessExplorer工具(来自Sysinternals)可以更直观地看到每个句柄的引用计数和未完成I/O数量。步骤7:结合其他命令如果怀疑是未完成I/O导致的,我们还可以使用:!thread#查看当前线程的状态,看是否在等待某个I/O操作!iochain#查看与线程关联的I/O请求包(IRP)链但是,需要注意的是,CloseHandle的调用线程在等待未完成I/O时,通常会处于等待状态(WaitReason可能是Executive或WrQueue等)。步骤8:使用WPA(WindowsPerformanceAnalyzer)进行更深入的分析引用[3]中提到使用xperf进行性能跟踪,我们可以捕获CloseHandle调用期间的内核事件,分析阻塞点。示例:使用WPA分析CloseHandle的堆栈,看是否有长时间的等待。总结:在WinDbg中,通过!handle命令我们可以:-列出所有句柄,找出可疑句柄(数量多、类型关键)-查看特定句柄的详细信息,特别是引用计数-结合其他命令(如!thread)分析线程状态但是,对于未完成I/O,!handle命令提供的信息有限,需要结合其他工具和方法。引用[1]中提到WinDbg!handle命令,以及任务管理器查看句柄数量,这些都可以作为辅助手段。另外,引用[2]中的示例代码展示了一个可能导致CloseHandle阻塞的场景:主线程等待一个长时间运行的线程(Sleep一小时)。在这种情况下,CloseHandle(hThread)在WaitForSingleObject返回后立即被调用,所以实际上不会阻塞,因为线程已经结束。但如果我们修改代码,不等待线程结束就直接CloseHandle,那么CloseHandle会立即返回(因为线程句柄的关闭不会影响线程执行)。然而,如果线程句柄被用于其他未完成操作(比如等待线程结束),则WaitForSingleObject会阻塞,而不是CloseHandle。因此,在实际调试中,我们需要根据具体情况分析。下面是一个使用!handle命令的示例:假设我们有一个进程,句柄0x1c是一个文件句柄,我们怀疑它导致CloseHandle缓慢:0:001>!handle0x1cfHandle1cTypeFileAttributes0GrantedAccess0x120089:ReadControl,SynchRead/List,ReadEA,ReadAttrHandleCount2PointerCount3Name\Device\HarddiskVolume2\test.txt这里HandleCount=2表示有两个句柄指向同一个对象(可能是当前进程或其他进程通过DuplicateHandle复制了句柄),PointerCount=3表示内核对象的总引用计数为3(包括内核模式引用)。如果PointerCount大于1,说明还有别的引用存在,CloseHandle调用后,该进程的句柄会被关闭,但对象不会销毁,因此CloseHandle不会阻塞。但是,如果这个文件句柄有未完成的异步I/O,那么CloseHandle会等待I/O完成,即使引用计数为1。因此,要排查未完成I/O,我们可能需要更深入的工具,如WPA或使用驱动调试。对于未完成I/O,我们可以尝试使用以下命令:!fileobj<对象地址>注意:!fileobj是WinDbg的一个扩展命令,需要安装Windows调试工具包,并且需要符号支持。它能够显示文件对象的详细信息,包括当前挂起的IRP。示例:首先通过!handle获取文件对象的地址(在输出中,Handle信息里通常会包含对象地址,如Object:xxxxxxxx)然后执行:!fileobjxxxxxxxx在输出中,我们可以查看当前是否有未完成的IRP。综上所述,排查CloseHandle缓慢的步骤:1.使用!handle00列出所有句柄,观察是否有异常。2.对可疑句柄使用!handle<handle>f获取详细信息,关注引用计数。3.如果是文件句柄,使用!fileobj<对象地址>查看未完成IRP。4.如果是线程或进程句柄,注意线程/进程是否已经终止(未终止的线程/进程不会导致CloseHandle阻塞,除非有未完成的操作,但通常不会)。5.使用WPA进行性能跟踪,捕获CloseHandle调用时的内核堆栈,分析等待事件。引用[1]中提到的WinDbg!handle命令是基础,引用[3]中的xperf命令(即WPA的前端)是更深入分析的工具。最后,根据引用[1]中的最佳实践,在代码中应确保异步I/O操作完成或显式取消后再关闭句柄,避免阻塞。</think>### 在 WinDbg 中使用 `!handle` 命令排查 CloseHandle 调用缓慢问题 #### 排查步骤及命令详解 1. **获取目标进程句柄列表** ```bash !handle 0 0 # 列出所有句柄的摘要信息 ``` **输出解析**: ``` Handle 0000000000000004 Type File GrantedAccess 0x120089 HandleCount 2 PointerCount 3 Name \Device\HarddiskVolume2\test.txt ``` - **关键字段**: - `HandleCount`:用户模式引用计数(>1 表示存在未释放引用) - `PointerCount`:内核模式总引用计数 - `Name`:对象关联资源路径(用于识别阻塞源) 2. **查看特定句柄的详细信息** ```bash !handle <HandleValue> f # 示例:!handle 0000000000000004 f ``` **关键诊断点**: - **引用计数异常**: ``` Object Specific Information File Object 0xffffe001a1b2b080 CurrentByteOffset 0 ``` `PointerCount` 值高表示存在未释放引用[^1] - **未完成 I/O 操作**: ``` Flags 0x40000 Asynchronous I/O ``` 出现 `Asynchronous I/O` 标志需检查挂起操作 3. **检查内核对象引用** ```bash !object <ObjectAddress> # 从!handle输出获取对象地址 ``` **输出分析**: ``` Object: ffffe001a1b2b080 Type: (ffff9480f1d0b0c0) File HandleCount: 1 PointerCount: 3 ``` `PointerCount > HandleCount` 表明存在内核驱动未释放引用 4. **定位 I/O 阻塞源** ```bash !irpfind <ObjectAddress> # 查找关联的IRP包 !irp <IrpAddress> # 分析I/O状态 ``` **阻塞场景判断**: - `Irp->CurrentLocation != 0`:I/O 未完成 - `Irp->Cancel = true`:取消操作被挂起 #### 典型问题诊断案例 1. **异步 I/O 未完成** ```bash !handle 0 0 # 发现文件句柄Flags含"Asynchronous I/O" !thread # 查看线程状态 !irpfind # 查找挂起IRP ``` **解决方案**: ```c CancelIoEx(hFile, NULL); // 显式取消I/O CloseHandle(hFile); ``` 2. **对象引用泄漏** ```bash !handle 000000000000000c f # 输出:PointerCount=5, HandleCount=1 !object ffffe001a1b2b080 ``` **解决方法**: - 检查跨进程 `DuplicateHandle()` 调用 - 使用 Process Explorer 定位持有者进程 3. **驱动资源阻塞** ```bash !handle <DeviceHandle> f # 输出含"\Driver\AVDriver"等第三方驱动名 !locks # 检查内核锁争用 ``` **处理建议**: - 更新或禁用问题驱动 - 检查驱动过滤栈 `!filtarget` #### 诊断流程图 ```mermaid graph TD A[CloseHandle卡顿] --> B[!handle 0 0] B --> C{存在高引用计数?} C -->|是| D[!object 分析内核引用] C -->|否| E{存在异步I/O标志?} E -->|是| F[!irpfind 查挂起操作] E -->|否| G[检查系统资源瓶颈] D --> H[定位未释放的引用源] F --> I[取消或等待I/O完成] G --> J[检查内存/锁争用] ``` #### 补充工具建议 1. **实时监控**: ```bash .logopen c:\handle_log.txt # 开启日志记录 !htrace -enable # 启用句柄跟踪 # 重现问题后 !htrace -snapshot # 分析句柄变化 ``` 2. **性能分析**: ```bash xperf -on PROC_THREAD+LOADER -stackwalk CloseHandle ``` 捕获内核调用栈(需 WPA 工具分析)[^3] 通过上述方法,可精确识别 CloseHandle 阻塞的根本原因,针对性解决句柄泄露、异步 I/O 未完成或驱动兼容性问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值