27.5.使用 DTrace

DTrace 脚本由一个或多个探针或检测点的列表组成,每个探针都与一个动作相关联。每当探针的条件满足时,相关联的动作就会执行。例如,当文件被打开,进程启动,或者代码行执行时可能会发生某些操作。动作可能是记录一些信息或修改上下文变量。读取和写入上下文变量能让探针共享信息并合作分析不同事件之间的相关性。

要查看所有探针,管理员可以执行以下命令:

# dtrace -l | more

每个探针都有一个 ID,一个 PROVIDER (dtrace 或 fbt),一个 MODULE 和一个 FUNCTION NAME。有关此命令的更多信息,请参阅 dtrace(1)。

本节中的示例概述了如何使用 DTrace Toolkit 中两个完全支持的脚本:hotkernel 和 procsystime 脚本。

hotkernel 脚本旨在识别哪个函数占用了最多的内核时间。它将生成类似以下的输出:

# cd /usr/local/share/dtrace-toolkit
# ./hotkernel
Sampling... Hit Ctrl-C to end.

按照指示,使用 Ctrl+C 组合键来停止进程。在终止时,脚本将显示一列内核函数和时间信息,按时间递增的顺序排序输出:

kernel`_thread_lock_flags                                   2   0.0%
0xc1097063                                                  2   0.0%
kernel`sched_userret                                        2   0.0%
kernel`kern_select                                          2   0.0%
kernel`generic_copyin                                       3   0.0%
kernel`_mtx_assert                                          3   0.0%
kernel`vm_fault                                             3   0.0%
kernel`sopoll_generic                                       3   0.0%
kernel`fixup_filename                                       4   0.0%
kernel`_isitmyx                                             4   0.0%
kernel`find_instance                                        4   0.0%
kernel`_mtx_unlock_flags                                    5   0.0%
kernel`syscall                                              5   0.0%
kernel`DELAY                                                5   0.0%
0xc108a253                                                  6   0.0%
kernel`witness_lock                                         7   0.0%
kernel`read_aux_data_no_wait                                7   0.0%
kernel`Xint0x80_syscall                                     7   0.0%
kernel`witness_checkorder                                   7   0.0%
kernel`sse2_pagezero                                        8   0.0%
kernel`strncmp                                              9   0.0%
kernel`spinlock_exit                                       10   0.0%
kernel`_mtx_lock_flags                                     11   0.0%
kernel`witness_unlock                                      15   0.0%
kernel`sched_idletd                                       137   0.3%
0xc10981a5                                              42139  99.3%

该脚本还可以与内核模块一起使用。要使用此功能,请使用以下命令运行脚本: -m

# ./hotkernel -m
Sampling... Hit Ctrl-C to end.
^C
MODULE                                                  COUNT   PCNT
0xc107882e                                                  1   0.0%
0xc10e6aa4                                                  1   0.0%
0xc1076983                                                  1   0.0%
0xc109708a                                                  1   0.0%
0xc1075a5d                                                  1   0.0%
0xc1077325                                                  1   0.0%
0xc108a245                                                  1   0.0%
0xc107730d                                                  1   0.0%
0xc1097063                                                  2   0.0%
0xc108a253                                                 73   0.0%
kernel                                                    874   0.4%
0xc10981a5                                             213781  99.6%

procsystime 脚本捕获并打印给定进程 ID ( PID )或进程名称的系统调用时间使用情况。在以下示例中,生成了/bin/csh 的新实例。然后,执行了 procsystime 并保持等待,同时在另一个 csh 的实例上键入了一些命令。这是此测试的结果:

# ./procsystime -n csh
Tracing... Hit Ctrl-C to end...
^C

Elapsed Times for processes csh,

         SYSCALL          TIME (ns)
          getpid               6131
       sigreturn               8121
           close              19127
           fcntl              19959
             dup              26955
         setpgid              28070
            stat              31899
       setitimer              40938
           wait4              62717
       sigaction              67372
     sigprocmask             119091
    gettimeofday             183710
           write             263242
          execve             492547
           ioctl             770073
           vfork            3258923
      sigsuspend            6985124
            read         3988049784

如图所示,read() 系统调用使用了最多的纳秒时间,而 getpid() 系统调用使用了最少的时间。

最后更新于

FreeBSD 中文社区