Solaris 模块调试器指南

分配器日志记录工具

如果为高速缓存设置了 KMF_AUDIT,则内核内存分配器会对记录其最近活动历史的日志进行维护。此事务日志记录的是 bufctl_audit 记录。如果同时设置了 KMF_AUDITKMF_CONTENTS 标志,则分配器会生成一个内容日志,其中记录了已分配和已释放缓冲区的部分实际内容。 内容日志的结构和用法不在本文档的讨论范围之内。本节将讨论事务日志。

MDB 提供了用于显示事务日志的多种工具。最简单的工具是 ::walk kmem_log,用于将日志中的事务作为一系列 bufctl_audit_t 指针进行列显:

> ::walk kmem_log

70128340

701282e0

70128280

70128220

701281c0

...

> 70128340$<bufctl_audit

0x70128340:     next            addr            slab

                70ac1d40        70bc4ea8        70bb7c00

0x7012834c:     cache           timestamp       thread

                70039428        e1bd7abe721     70aacde0

0x7012835c:     lastlog         contents        stackdepth

                701282e0        7018f340        4

0x70128368:

                kmem_cache_free+0x24

                nfs3_sync+0x3c

                vfs_sync+0x84

                syssync+4

查看整个事务日志的更好方法是使用 ::kmem_log 命令:

> ::kmem_log

CPU ADDR     BUFADDR         TIMESTAMP THREAD

  0 70128340 70bc4ea8      e1bd7abe721 70aacde0

  0 701282e0 70bc4ea8      e1bd7aa86fa 70aacde0

  0 70128280 70bc4ea8      e1bd7aa27dd 70aacde0

  0 70128220 70bc4ea8      e1bd7a98a6e 70aacde0

  0 701281c0 70d03738      e1bd7a8e3e0 70aacde0

  ...

  0 70127140 70cf78a0      e1bd78035ad 70aacde0

  0 701270e0 709cf6c0      e1bd6d2573a 40033e60

  0 70127080 70cedf20      e1bd6d1e984 40033e60

  0 70127020 70b09578      e1bd5fc1791 40033e60

  0 70126fc0 70cf78a0      e1bd5fb6b5a 40033e60

  0 70126f60 705ed388      e1bd5fb080d 40033e60

  0 70126f00 705ed388      e1bd551ff73 70aacde0

  ...

::kmem_log 的输出按时间标记进行降序排列。ADDR 列是对应于该事务的 bufctl_audit 结构;BUFADDR 指向实际缓冲区。

这些数字表示(分配和释放的)缓冲区中的事务。如果特定的缓冲区损坏,则在事务日志中找到该缓冲区,然后确定在其他哪些事务中涉及执行事务的线程可能会有所帮助。 这有助于对分配(或释放)缓冲区前后所发生的事件的顺序有一个完整的了解。

可以使用 ::bufctl 命令过滤遍历事务日志的输出。 ::bufctl -a 命令用于按缓冲区地址过滤事务日志中的缓冲区。 以下是对缓冲区 0x70b09578 进行过滤的示例:

> ::walk kmem_log | ::bufctl -a 0x70b09578

ADDR     BUFADDR   TIMESTAMP   THREAD   CALLER

70127020 70b09578  e1bd5fc1791 40033e60 biodone+0x108

70126e40 70b09578  e1bd55062da 70aacde0 pageio_setup+0x268

70126de0 70b09578  e1bd52b2317 40033e60 biodone+0x108

70126c00 70b09578  e1bd497ee8e 70aacde0 pageio_setup+0x268

70120480 70b09578  e1bd21c5e2a 70aacde0 elfexec+0x9f0

70120060 70b09578  e1bd20f5ab5 70aacde0 getelfhead+0x100

7011ef20 70b09578  e1bd1e9a1dd 70aacde0 ufs_getpage_miss+0x354

7011d720 70b09578  e1bd1170dc4 70aacde0 pageio_setup+0x268

70117d80 70b09578  e1bcff6ff27 70bc2480 elfexec+0x9f0

70117960 70b09578  e1bcfea4a9f 70bc2480 getelfhead+0x100

...

本示例说明一个特定的缓冲区可以在许多事务中使用。


注意 –

请记住,kmem 事务日志是内核内存分配器生成的事务不完整记录。会根据需要删除日志中的较旧项,以便保持日志大小不变。


::allocdby::freedby dcmd 提供了汇总与特定线程关联的事务的便利方法。 以下示例列出了线程 0x70aacde0 最近执行的分配:

> 0x70aacde0::allocdby

BUFCTL      TIMESTAMP CALLER

70d4d8c0  e1edb14511a allocb+0x88

70d4e8a0  e1edb142472 dblk_constructor+0xc

70d4a240  e1edb13dd4f allocb+0x88

70d4e840  e1edb13aeec dblk_constructor+0xc

70d4d860  e1ed8344071 allocb+0x88

70d4e7e0  e1ed8342536 dblk_constructor+0xc

70d4a1e0  e1ed82b3a3c allocb+0x88

70a53f80  e1ed82b0b91 dblk_constructor+0xc

70d4d800  e1e9b663b92 allocb+0x88

通过检查 bufctl_audit 记录,可以了解特定线程最近的活动。