接下来的示例程序使用 DTrace profile 提供器实现基于时间的简单计数器。该 profile 提供器可以根据 D 程序中的描述创建新的探测器。如果为某个整数 n 创建一个名为 profile:::tick-n sec 的探测器,该 profile 提供器将创建一个触发间隔为 n 秒的探测器。键入以下源代码,并将其保存在名为 counter.d 的文件中:
/* * Count off and report the number of seconds elapsed */ dtrace:::BEGIN { i = 0; } profile:::tick-1sec { i = i + 1; trace(i); } dtrace:::END { trace(i); }
执行时,程序将统计已用的秒数,直到按下 Ctrl-C 组合键为止,然后在结尾显示总计:
# dtrace -s counter.d dtrace: script 'counter.d' matched 3 probes CPU ID FUNCTION:NAME 0 25499 :tick-1sec 1 0 25499 :tick-1sec 2 0 25499 :tick-1sec 3 0 25499 :tick-1sec 4 0 25499 :tick-1sec 5 0 25499 :tick-1sec 6 ^C 0 2 :END 6 # |
程序的前三行为注释,用于解释程序将执行的操作。与 C、C++、Java 编程语言类似,D 编译器会忽略 /* 和 */ 符号之间的任何字符。可以在 D 程序中的任何位置使用注释,包括探测器子句的内部和外部。
BEGIN 探测器子句定义了一个名为 i 的新变量,并使用以下语句将整数值零赋给该变量:
i = 0;
与 C、C++ 和 Java 编程语言不同,只需在程序语句中使用便可创建 D 变量,而无需进行显式变量声明。在程序中首次使用某个变量时,将会根据变量的第一个赋值的类型设置其类型。在程序的生命周期中,每个变量仅有一个类型,因此后续引用的类型必须与初始赋值的类型相同。在 counter.d 中,变量 i 首先被赋值为整型常数零,因此其类型设置为 int。D 提供了与 C 相同的基本整数数据类型,包括:
char |
字符或单字节整数 |
int |
缺省整数 |
short |
短整数 |
long |
长整数 |
long long |
扩展的长整数 |
这些类型的大小取决于操作系统内核的数据模型,如第 2 章中所述。D 还为各种固定大小的带符号整数类型和无符号整数类型以及由操作系统定义的大量其他类型提供了内置的友好名称。
counter.d 的中心部分是使计数器 i 递增的探测器子句:
profile:::tick-1sec { i = i + 1; trace(i); }
此子句将探测器命名为 profile:::tick-1sec,以指示 profile 提供器创建一个在可用处理器中每秒触发一次的新探测器。该子句包括两条语句,第一条语句指定 i 的值为前一个值加一,第二条语句跟踪 i 的新值。所有常见的 C 算术运算符均可用于 D 程序;在第 2 章中可以找到完整的列表。与 C 中一样,++ 运算符也可以用作以一为增量递增相应变量的简写。trace() 函数接受任何 D 表达式作为其参数,因此可以更简明地编写 counter.d,如下所示:
profile:::tick-1sec { trace(++i); }
如果要显式控制变量 i 的类型,可以在为变量赋值时将所需类型括在括号中,以便将整数零强制转换为特定类型。例如,如果要确定 D 中 char 的最大大小,可以按照如下所示更改 BEGIN 子句:
dtrace:::BEGIN { i = (char)0; }
在运行 counter.d 一段时间后,应看到跟踪的值增大,然后绕回为零。如果您没有耐心等待值绕回,可尝试将 profile 探测器名称更改为 profile:::tick-100msec,使计数器每 100 毫秒递增一次或每秒递增 10 次。