对象用法

进程创建并使用内核对象来执行工作。就像内存可能会泄露或滥用(例如释放后使用)一样,内核对象的句柄也可能会被泄露或滥用(例如关闭后使用)。

标识名工具

为了帮助开发者诊断处理问题,请使用 handles 工具,以下是一个进程 29831 示例(即 wlancfg.cm):

$ handles 29831
    handle   koid rkoid     rights type
0xa8d44a0f: 29973       0x0000d0ef vmo
0xa8e44aab: 29847 29846 0x0000f00e channel
0xa8d44a0b: 29972       0x0000d0ef vmo
0xa8e42413:  9931  9930 0x0000f00e channel
0xa8d44a07: 29971       0x0000d0ef vmo
0xa8f44a1f: 29969 29970 0x0000f00e channel
0xa8a44a3b: 29964       0x0000d0ef vmo
0xa8d44a17: 29962 29963 0x0000f00e channel
0xa8844a43: 29961       0x0000d0ef vmo
0xa8f44a4b: 29960       0x0000d0ef vmo
0xa8e44a3f: 29959       0x0000d0ef vmo
0xa8e44a23: 29958       0x0000800f port
0xa8f44a2f: 29957       0x0000d0ef vmo
0xa8644a53: 29911       0x0000d0ef vmo
0xa8a44a7f: 29908       0x0000d0ef vmo
0xa8844a6b: 29907       0x0000d0ef vmo
0xa8f44a63: 29906       0x0000d0ef vmo
0xa8844a6f: 29905       0x0000d0ef vmo
0xa8f44a8b: 29904       0x0000d0ef vmo
0xa8944a9f: 29903       0x0000d0ef vmo
0xa8444a83: 29900       0x0000800f vmar
0xa8e44a77: 29845       0x0000d0ef vmo
0xa8f44a8f:  1034       0x0000d0f7 vmo
0xa8d44aa3:  1129       0x0000d00b log
0xa8d44abf:  1129       0x0000d00b log
0xa8d44abb:  1129       0x0000d00b log
0xa8644aef: 29827 29828 0x0000f00e channel
0xa8844ac3: 29826  8711 0x0007dfcf job
0xa8144afb: 29825 29824 0x0000f00e channel
0xa8e44adb: 29816 29817 0x0000f00e channel
0xa8e44ad3: 29776 29777 0x0000f00e channel
0xa894496b: 29766 29767 0x0000f00e channel
0xa8d44a97: 29833 29831 0x0004d2cf thread
0xa8d44a93: 29832       0x0000801f vmar
0xa8d44aaf: 29831 29826 0x0006d3cf process
0xa8f44a73: 29850       0x0000d00b log
0xa8f44af3: 29768 29769 0x0000f00e channel
0xa8e44aa7: 29834 29835 0x0000f00e channel
38 handles

handles <pid> 工具会转储进程句柄表,其中包含在调用时特定进程的所有可访问句柄。

对于每个句柄,该工具都会输出句柄值、所指向对象的 koid、相关的 koid (rkoid)(如果对象具有相关对象)、句柄右侧和对象类型。

在上面的示例中,它显示了 38 个唯一句柄,这些句柄映射到 36 个唯一对象;其中 3 个句柄指向使用 koid 为 1129 的同一“log”对象。

请注意,该工具不一定会显示所有活跃的对象。例如,即使线程没有打开的句柄,线程也可以保持活动状态,并且 VMO 可由关联的 VMAR 保持活动状态。

handles 工具支持按对象类型进行过滤和反向过滤;使用 handles --help 可查看所有选项。

调试程序中的句柄

您可以使用调试程序查看句柄信息。为此,请附加到相关进程并运行 handles 命令。这会显示句柄值、对象类型和对象 koid:

[zxdb] handles
  504103211  ZX_OBJ_TYPE_VMO        27851
  504103271  ZX_OBJ_TYPE_VMO        27719
  505151859  ZX_OBJ_TYPE_VMO        27720
  505151867  ZX_OBJ_TYPE_VMO        27718
  506200511  ZX_OBJ_TYPE_PORT       27976
  507249163  ZX_OBJ_TYPE_VMAR       27716
  508297363  ZX_OBJ_TYPE_VMO        28200
  508297379  ZX_OBJ_TYPE_VMO        28187
  508297387  ZX_OBJ_TYPE_SOCKET     28189
  508297731  ZX_OBJ_TYPE_CLOCK       1263
  508297735  ZX_OBJ_TYPE_LOG         1275
  508297755  ZX_OBJ_TYPE_LOG         1275

您还可以通过调用 handle 并指定句柄值来查看句柄的基本信息:

[zxdb] handle 508302371
          Type  ZX_OBJ_TYPE_CHANNEL
         Value  508302371
        Rights  ZX_RIGHT_TRANSFER
                ZX_RIGHT_READ
                ZX_RIGHT_WRITE
                ZX_RIGHT_SIGNAL
                ZX_RIGHT_SIGNAL_PEER
                ZX_RIGHT_WAIT
                ZX_RIGHT_INSPECT
          Koid  31062
  Related koid  31061

如果句柄引用的对象与其他对象(例如渠道的另一端或作业的父级)相关,则 related_koid 是该其他对象的 koid。如果没有其他相关对象,则此值为零。在本例中,相关的 koid 是渠道的另一端。这种关系是不可变的:即使相关对象已不存在,对象的 related_koid 也不会改变。

标识名政策有误

使用关闭的句柄或关闭已关闭的句柄都是错误,可能会导致难以诊断的错误。

为帮助开发者发现这些问题,可以使用 zx_job_set_policy 以及条件 ZX_POL_BAD_HANDLE 和操作 ZX_POL_ACTION_ALLOW_EXCEPTION 激活“错误句柄”作业政策。在采用此政策的作业下启动进程时,如果使用已关闭的句柄,将产生异常:如果未处理,则会终止进程并记录违规的调用堆栈,或者可能被调试程序捕获以进行交互式问题排查。