一些破坏性操作仅对特定进程具有破坏性。具有 dtrace_proc 或 dtrace_user 权限的用户可以使用这些操作。有关 DTrace 安全权限的详细信息,请参见第 35 章。
void stop(void)
当触发已启用的探测器的进程接下来退出内核时,stop() 操作将强制停止该进程,就像由 proc(4) 操作停止一样。prun(1) 实用程序可用于恢复由 stop() 操作停止的进程。stop() 操作可用于在任何 DTrace 探测器位置停止进程。此操作可用于在特定状态下,捕获难以使用简单断点获取的程序,然后将一个传统调试器(如 mdb(1))附加至该进程。您也可以使用 gcore(1) 实用程序将已停止进程的状态保存在一个核心转储文件中,供以后进行分析。
void raise(int signal)
raise() 操作将指定的信号发送至当前正在运行的进程。此操作与使用 kill(1) 命令向进程发送信号类似。raise() 操作可用于在进程执行过程中的一个准确时间点发送信号。
void copyout(void *buf, uintptr_t addr, size_t nbytes)
copyout() 操作在与当前线程关联的进程的地址空间中,从 buf 指定的缓冲区中复制 nbytes 到 addr 指定的地址。如果用户空间地址与当前地址空间中有效的错误页面不对应,则将生成错误。
void copyoutstr(string str, uintptr_t addr, size_t maxlen)
copyoutstr() 操作在与当前线程关联的进程的地址空间中,将 str 指定的字符串复制到 addr 指定的地址。如果用户空间地址与当前地址空间中有效的错误页面不对应,则将生成错误。字符串长度限于 strsize 选项指定的值。有关详细信息,请参见第 16 章。
void system(string program, ...)
system() 操作将导致执行 program 指定的程序,就像将该程序作为输入提供给 shell 一样。program 字符串可以包含任何 printf()/printa() 格式转换。指定的参数必须与格式转换匹配。有关有效的格式转换的详细信息,请参阅第 12 章。
以下示例每秒运行 date(1) 命令一次:
# dtrace -wqn tick-1sec'{system("date")}' Tue Jul 20 11:56:26 CDT 2004 Tue Jul 20 11:56:27 CDT 2004 Tue Jul 20 11:56:28 CDT 2004 Tue Jul 20 11:56:29 CDT 2004 Tue Jul 20 11:56:30 CDT 2004 |
以下示例通过在 program 字符串中使用 printf() 转换,同时使用传统过滤工具(如管道),更详细地说明了该操作的用法。
#pragma D option destructive #pragma D option quiet proc:::signal-send /args[2] == SIGINT/ { printf("SIGINT sent to %s by ", args[1]->pr_fname); system("getent passwd %d | cut -d: -f5", uid); }
运行上面的脚本将会生成与以下示例类似的输出:
# ./whosend.d SIGINT sent to MozillaFirebird- by Bryan Cantrill SIGINT sent to run-mozilla.sh by Bryan Cantrill ^C SIGINT sent to dtrace by Bryan Cantrill |
在触发探测器的上下文中不会执行指定的命令,此命令是在用户级处理包含 system() 操作的详细信息的缓冲区时执行的。进行此处理的方式和时间取决于第 11 章中介绍的缓冲策略。使用缺省缓冲策略时,缓冲区处理速率由 switchrate 选项指定。如果将 switchrate 显式地调整到高于其缺省值(一秒),则将会看到 system() 中的固有延迟,如下例所示:
#pragma D option quiet #pragma D option destructive #pragma D option switchrate=5sec tick-1sec /n++ < 5/ { printf("walltime : %Y\n", walltimestamp); printf("date : "); system("date"); printf("\n"); } tick-1sec /n == 5/ { exit(0); }
运行上面的脚本将会生成与以下示例类似的输出:
# dtrace -s ./time.d walltime : 2004 Jul 20 13:26:30 date : Tue Jul 20 13:26:35 CDT 2004 walltime : 2004 Jul 20 13:26:31 date : Tue Jul 20 13:26:35 CDT 2004 walltime : 2004 Jul 20 13:26:32 date : Tue Jul 20 13:26:35 CDT 2004 walltime : 2004 Jul 20 13:26:33 date : Tue Jul 20 13:26:35 CDT 2004 walltime : 2004 Jul 20 13:26:34 date : Tue Jul 20 13:26:35 CDT 2004 |
请注意,walltime 值会不同,但 date 值相同。此结果反映了一个事实,即仅当处理缓冲区而不是记录 system() 操作时,才会执行 date(1) 命令。