27.5.使用 DTrace
DTrace 脚本由一个或多个探针或检测点的列表组成,每个探针都与一个动作相关联。每当探针的条件满足时,相关联的动作就会执行。例如,当文件被打开,进程启动,或者代码行执行时可能会发生某些操作。动作可能是记录一些信息或修改上下文变量。读取和写入上下文变量能让探针共享信息并合作分析不同事件之间的相关性。
要查看所有探针,管理员可以执行以下命令:
每个探针都有一个 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() 系统调用使用了最少的时间。