Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1315359
  • 博文数量: 554
  • 博客积分: 10425
  • 博客等级: 上将
  • 技术积分: 7555
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-09 09:49
文章分类

全部博文(554)

文章存档

2012年(1)

2011年(1)

2009年(8)

2008年(544)

分类:

2008-04-11 15:48:33


内置
第8 章• 类型和常量定义105
}
在可以使用相应类型的全局变量的任何位置都可以使用内置名称。如果在编译时内置表达
式可以计算为整数或字符串常量,则还可以在要求常量表达式(如标量数组维度)的上下
文中使用内置名称。
对内置表达式进行语法错误验证是计算指令过程的一部分。根据用于D赋值运算符(=) 的相
同规则,表达式结果类型必须与内置指令所定义的类型兼容。内置表达式不可以引用内置
标识符本身:不允许使用递归定义。
DTrace 软件包在系统目录/usr/lib/dtrace 中安装大量的D源文件,这些源文件中包含可以
在D 程序中使用的内置指令。例如,signal.d 库包括以下格式的指令:
inline int SIGHUP = 1;
inline int SIGINT = 2;
inline int SIGQUIT = 3;
...
这些内置定义使您可以访问当前Solaris 信号名称集,如signal( 3HEAD) 中所述。类似地,
errno.d 库包含C errno 常量的内置指令,如Intro(2) 中所述。
缺省情况下,D编辑器自动包括所提供的所有D库文件,以便可以在任何D程序中使用这
些定义。
类型名称空间
本节讨论D名称空间以及与各种类型有关的名称空间问题。在传统语言(如ANSI-C)中,
类型可见性由类型是嵌入在函数中还是嵌入在其他声明中来确定。在C 程序的外部范围中
声明的类型与单个全局名称空间关联,这些类型在整个程序中可见。C 头文件中定义的类
型通常包括在此外部范围中。与这些语言不同,D可以访问多个外部范围中的类型。
D是一种可以很方便地在软件栈的多个层(包括操作系统内核、关联的可装入内核模块集
和系统上正在运行的用户进程)中进行动态观察的语言。单个D程序可以实例化探测器,
以便从编译到独立二进制对象的多个内核模块或其他软件实体中收集数据。因此,在
DTrace 和D编译器可以使用的总体类型中,可能存在名称相同但定义不同的多种数据类
型。为了解决这种情况,D编译器将每种类型与所包含程序对象标识的名称空间关联。通
过在任何类型名称中指定对象名称和反引号(‘) 作用域运算符,可以访问特定程序对象的类
型。
例如,如果名为foo 的内核模块包含以下C 类型声明:
typedef struct bar {
int x;
类型名称空间
106 Solaris 动态跟踪指南• 2006 年7 月
} bar_t;
则可以在D 中使用以下类型名称来访问struct bar 和bar_t:
struct foo‘bar foo‘bar_t
在类型名称合适的任何上下文中(包括当为D探测子句中的D变量声明或强制类型转换表
达式指定类型时)都可以使用反引号运算符。
D编译器还提供了两种特殊的内置类型名称空间(分别使用C 和D)。C 类型名称空间最初
使用标准ANSI-C 内部类型(如int)填充。此外,使用C 预处理程序cpp(1) 并使用dtrace
-C 选项获取的类型定义将由C 范围处理并添加到其范围中。因此,可以将已可见的类型指
令所在的C 头文件包含到另一类型名称空间中,而不会引起编译错误。
D类型名称空间初始使用D内部类型(如int 和string)及内置D类型别名(如
uint32_t)填充。出现在D程序源代码中的任何新类型声明都将自动添加到D类型名称空
间中。如果在D程序中创建由来自其他名称空间的成员类型组成的复杂类型(如
struct),这些成员类型将会根据声明复制到D名称空间中。
当D编译器遇到未使用反引号运算符指定显式名称空间的类型声明时,编译器将会使用指
定的类型名称搜索活动的类型名称空间集以找到匹配项。将始终首先搜索C 名称空间,然
后搜索D名称空间。如果在C 或D名称空间中未找到类型名称,则将会按内核模块ID 的升
序搜索活动的内核模块的类型名称空间。此顺序保证,将首先搜索构成核心内核的二进制
对象,然后搜索任何可装入的内核模块,但不能保证可装入模块间的任何顺序属性。访问
可装入内核模块中定义的类型时,应使用作用域运算符以避免与其他内核模块发生类型名
称冲突。
D编译器使用为核心Solaris 内核模块提供的压缩ANSI-C 调试信息,以便自动访问与操作系
统源代码关联的类型,而无需访问相应的C 包含文件。此符号调试信息可能并不对系统上
的所有内核模块都可用。如果尝试访问模块的名称空间内的类型,而该模块缺少要用于
DTrace 的压缩C 调试信息,则D将会报告错误。
类型名称空间
第8 章• 类型和常量定义107
108
聚合
当检测系统以回答有关性能的问题时,可以考虑如何聚合数据以回答特定问题,而不是考
虑根据单个探测器收集的数据获得答案。例如,如果要知道某用户ID 进行的系统调用的数
目,您不必关心每次系统调用收集的数据, 只需要查看包含用户ID 和系统调用的表即可。
以前,您需要通过在每次系统调用时收集数据,并使用工具(如awk(1) 或perl(1))对数据
进行后期处理来回答此问题。但是在DTrace 中,聚合数据非常容易。本章介绍用于处理聚
合的DTrace 工具。
聚合函数
聚合函数具有以下属性:
f(f(x
0
) U f(x
1
) U ... U f(x
n
)) = f(x
0
U x
1
U ... U x
n
)
其中,xn 是一个包含任意数据的数据集。即,对整个数据集合的子集应用聚合函数,然后
再次对结果应用该聚合函数,得出的结果与对整个数据集合本身应用该函数相同。例如,
生成给定数据集之和的SUM 函数。如果原始数据由{2, 1, 2, 5, 4, 3, 6, 4, 2} 组成,则对整个集合
应用SUM 的结果将是{29}。同样,对由前三个元素组成的子集应用SUM 的结果将是{5},对
由接下来的三个元素组成的子集应用SUM 的结果将是{12},而对余下三个元素应用SUM 的结
果也是{12}。SUM 是一个聚合函数,因为将其应用于这些结果的集合{5, 12, 12} 与将SUM 应用
于原始数据生成的结果相同,即{29}。
并非所有函数都为聚合函数。用于确定集合的中间元素的MEDIAN 函数就是一个非聚合函
数。(中间元素的定义是:集合中大于它的元素数目与小于它的元素数目相同。)MEDIAN
是通过对集合进行排序,然后选择中间元素获取的。现在返回到最初的原始数据,如果对
由前三个元素组成的集合应用MEDIAN,则结果为{2}。(经过排序的集合为{1, 2, 2};{2} 是
由中间元素组成的集合。) 同样,对接下来的三个元素应用MEDIAN 将生成{4},而对最后三
个元素应用MEDIAN 将生成{4}。因此,对每个子集应用MEDIAN 将生成集合{2, 4, 4}。对此集
合应用MEDIAN 将生成结果{4}。但是,对原始集合进行排序将生成{1, 2, 2, 2, 3, 4, 4, 5, 6}。对
此集合应用MEDIAN 将生成{3}。因为这些结果不匹配,所以MEDIAN 不是聚合函数。
9第9 章
109
许多用于了解数据集的常见函数都是聚合函数。这些函数包括:用于计算集合中元素数目
的函数、用于计算集合的最小值和最大值的函数以及用于对集合中的所有元素求和的函
数。可通过用于计算集合中元素数目的函数和用于对集中的元素进行求和的函数,来确定
集合的运算方法。
但是,一些有用的函数并非聚合函数。这些函数包括:用于计算集合的模(最常见元素)
的函数、用于计算集合的中间元素值的函数以及用于计算集合的标准差的函数。
在跟踪数据时对数据应用聚合函数有许多优点:
 无需存储整个数据集。每次将新元素添加到集合中时,只要该集合由当前中间结果和新
元素组成,就将计算聚合函数。在计算新结果后,新元素可能会被废弃。此过程将成
倍降低数据点需要的存储空间(通常非常大)。
 数据收集不会导致异常可伸缩性问题。聚合函数允许在每个CPU 中保存中间结果,而不
是将中间结果保存在共享数据结构中。然后,DTrace 将对由每个CPU 中的中间结果组
成的集合应用聚合函数,以生成最终系统范围的结果。
聚合
DTrace 将聚合函数的结果存储在称为聚合的对象中。聚合结果使用类似于关联数组所用的
表达式元组来建立索引。在D中,聚合的语法如下所示:
@name[ keys ] = aggfunc ( args );
其中,name 是聚合的名称,keys 是用逗号分隔的D表达式列表,aggfunc 是其中一个DTrace
聚合函数,而args 是用逗号分隔的适用于聚合函数的参数列表。聚合name 是使用特殊字符
@ 作为前缀的D标识符。D程序中指定的所有聚合都为全局变量;没有线程局部聚合或子句
局部聚合。聚合名称保存在与其他D全局变量不同的标识符名称空间中。请记住,如果重
用名称,则a 和@a 不是同一变量。特殊聚合名称@ 可用于在简单D程序中命名匿名聚合。
D编译器将此名称视为聚合名称@_ 的别名。
下表中显示了DTrace 聚合函数。大多数聚合函数仅接受表示新数据的单个参数。
表9–1DTrace 聚合函数
函数名参数结果
count 无调用次数。
sum 标量表达式所指定表达式的总计值。
avg 标量表达式所指定表达式的算术平均值。
min 标量表达式所指定表达式中的最小值。
max 标量表达式所指定表达式中的最大值。
聚合
110 Solaris 动态跟踪指南• 2006 年7 月
表9–1DTrace 聚合函数(续)
函数名参数结果
lquantize 标量表达式、下
限、上限、步长值
所指定表达式的值的线性频数分布(按指定范围确定大
小)。递增最高存储桶中小于指定表达式的值。
quantize 标量表达式所指定表达式的值的二次方频数分布。递增最高二次方存
储桶中小于所指定表达式的值。
例如,要计算系统中write(2) 系统调用数,可以使用count() 聚合函数,并以提示性字符串
作为关键字:
syscall::write:entry
{
@counts["write system calls"] = count();
}
缺省情况下,当因为显式END 操作或用户按Ctrl-C 组合键而使进程终止时,dtrace 命令将
列显聚合结果。以下示例输出显示了运行此命令、等待几秒钟,然后按Ctrl-C 组合键的结
果:
# dtrace -s writes.d
dtrace: script ’./writes.d’ matched 1 probe
^C
write system calls 179
#
可以通过将execname 变量用作聚合的关键字来按每个进程名称计算系统调用的数目:
syscall::write:entry
{
@counts[execname] = count();
}
以下示例输出显示了运行此命令、等待几秒钟,然后按Ctrl-C 组合键的结果:
 
 
以上文章转自于 : http://developers.sun.com.cn/
阅读(408) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~