运行 ProbeVue

只有具有特权的用户或超级用户才可以进行动态跟踪。

权限和特权

这与AIX® 中的静态跟踪设施不同,后者执行的权限检查相对有限。 运行 probevue 命令需要特权是有原因的。 与 AIX 系统跟踪之类的静态跟踪工具相比, Vue 脚本可能会对系统性能产生更严重的影响。 这是因为系统跟踪的探针点是预定义且受限的。 ProbeVue 可能支持更多探测器点,并且可以在几乎任何位置定义探测器位置。 此外,探测器点的 ProbeVue 跟踪操作可能需要比探测器点的系统跟踪操作更长的时间才能发出,因为这些操作仅限于显式数据捕获。

此外, ProbeVue 允许您跟踪进程和读取内核全局变量,这两个变量都需要控制以防止安全隐患。 ProbeVue 会话还可以使用大量固定内存,并将 ProbeVue 的使用限制为具有特权的用户,从而降低拒绝服务攻击的风险。 ProbeVue 还允许管理员通过 SMIT 界面控制 ProbeVue 会话的内存使用情况。

根据是否启用了基于角色的访问控制 (RBAC),获取动态跟踪特权的方法会有所不同。 有关启用和禁用 RBAC 的详细信息,请参阅AIX手册。

请注意,在旧的或已禁用 RBAC 的方式中没有授权。 常规用户无法获取特权来运行 probevue 命令以启动动态跟踪会话或运行 probevctrl 命令以管理 ProbeVue。 只有超级用户具有使用这两项功能的特权。 使用 ProbeVue 时请勿禁用 RBAC ,除非您希望将此工具仅限于 root 用户。

启用了 RBAC 的方式

可通过授权获取 RBAC 系统中的特权。 权限是与有关安全的函数或命令相关联的文本字符串。 授权会提供机制以授予您执行特权操作的权限。 只有具有足够权限的用户可发出 probevue 命令并启动动态跟踪会话。

aix.ras.probevue.trace.user.self
此权限允许您在用户空间中跟踪他们的应用程序。 要跟踪的进程的用户标识必须与调用 probevue 命令的用户的真实用户标识相同。 此权限允许您为进程启用 uft 探针管理器提供的探针点。 但是,要跟踪的进程的有效、真实和已保存的用户标识必须都相同。 因此,您不能只使用此权限来跟踪 setuid 程序。
aix.ras.probevue.trace.user
此权限允许您跟踪用户空间中的任何应用程序,包括 setuid 程序和超级用户启动的程序。 授予此权限时要小心。 此权限允许您发出 probevue 命令并为系统上的任何进程启用 uft 探针管理器提供的探针点。
aix.ras.probevue.trace.syscall.self
此权限允许您跟踪系统调用的应用程序发出的系统调用。 发出系统调用的进程的有效、真实和已保存的用户标识必须与调用 probevue 命令的用户的真实用户标识相同或等价。 此权限允许您为进程启用 syscall 探针管理器提供的探针点。 调查规范的第二个字段必须表示您所启动进程的进程标识。
aix.ras.probevue.trace.syscall
此权限允许您跟踪系统上的任何应用程序(包括 setuid 程序和超级用户启动的应用程序)发出的系统调用。 授予此权限时要小心。 此权限允许您发出 probevue 命令并为任何进程启用 syscall 探针管理器提供的探针点。 调查规范的第二个字段可设为进程标识以调查特定的进程或设为 * 以调查所有进程。
aix.ras.probevue.trace
此权限允许您跟踪整个系统并包括前面部分中所定义的所有权限。 您还可以在运行 probevue 命令时访问和读取内核变量,使用 systrace 探测器管理器跟踪系统跟踪事件 以及使用时间间隔探测器管理器跟踪 CPU 绑定探测器。 使用此授权时请小心。
aix.ras.probevue.manage
此授权允许您管理 ProbeVue。 这包括更改不同的 ProbeVue 参数的值,启动或停止 ProbeVue 以及在运行 probevctrl 命令时查看所有用户的动态跟踪会话的详细信息。 如果没有此授权,您可以使用 probevctrl 命令来查看由您启动的动态跟踪会话的会话数据或查看 ProbeVue 参数的当前值。
aix.ras.probevue.rase
此授权允许您访问一组具有高度特权的 "RAS 事件" Vue 函数,这些函数可以生成系统和 LMT 跟踪记录,创建实时转储,甚至导致系统异常终止。 必须谨慎控制此特权。
aix.ras.probevue
此权限将授予所有动态跟踪特权并等同于前面所有权限的组合。

缺省情况下,会为超级用户(或 root 用户)指定所有这些权限。 其他用户则需要通过创建具有一组权限的角色并将该角色指定用户的方法来获取权限。 用户还需要将角色切换至具有为动态跟踪定义的必需权限的角色,然后才能调用 probevue 命令。 以下脚本示例说明了如何为用户“joe”提供权限以启用“joe”启动的进程的用户空间和系统调用调查。

 	mkrole authorizations=
   "aix.ras.probevue.trace.user.self,aix.ras.probevue.trace.syscall.self" 
   apptrace
	chuser roles=apptrace joe
	setkst -t roleTR

ng 命令:

swrole apptrace
注: 时间间隔探测器管理器没有与其关联的特定权限。 如果您有任何 aix.ras.probevue.trace* 权限,那么可以启用时间间隔探针点。

ProbeVue 特权

下表列出了可用于 ProbeVue 的特权。 同时还提供了每个特权以及映射至该特权的权限的描述。 特权将形成一个层次结构,其中父代特权包含与其子代特权相关联的所有权限,但是它也可以包括其他特权。

表 1. ProbeVue 特权
特权 描述 授权 关联命令
PV_PROBEVUE_ TRC_USER_SELF 允许某个进程使用相同的真实用户标识在其他进程上启用动态用户空间探针点。 aix.ras.probevue.trace.user.self aix.ras.probevue.trace.user aix.ras.probevue.trace aix.ras.probevue probevue
PV_PROBEVUE_ TRC_USER 允许进程启用动态用户空间探针点。 包括 PV_PROBEVUE_ TRC_USER_SELF 特权。 aix.ras.probevue.trace.user aix.ras.probevue.trace aix.ras.probevue probevue
PV_PROBEVUE_ TRC_SYSCALL_SELF 允许某个进程使用相同的真实用户标识在其他进程上启用动态系统调用探针点。 aix.ras.probevue.trace.syscall.self aix.ras.probevue.trace.syscall aix.ras.probevue.trace aix.ras.probevue probevue
PV_PROBEVUE_ TRC_SYSCALL 允许进程启用动态系统调用空间探针点。 包括 PV_PROBEVUE_ TRC_SYSCALL_

SELF 特权。

aix.ras.probevue.trace.syscall aix.ras.probevue.trace aix.ras.probevue probevue
PV_PROBEVUE _TRC_KERNEL 允许进程在动态跟踪时访问内核数据。 aix.ras.probevue.trace aix.ras.probevue probevue
PV_PROBEVUE_ MANAGE 允许进程管理 ProbeVue aix.ras.probevue.manage aix.ras.probevue probevctrl
PV_PROBEVUE_ RASE 授权使用受限“RAS 事件”函数。 aix.ras.probevue.rase aix.ras.probevue probevue
PV_PROBEVUE_ 等同于上述所有特权的组合 (PV_PROBEVUE_*)。 aix.ras.probevue Probevue probevctrl

ProbeVue 参数

AIX 提供了一组可用于调整 ProbeVueProbeVue 框架的参数。 这些参数允许您指定 ProbeVue 框架对资源使用情况的全局限制以及为个别用户指定资源使用情况。
注: 探测器管理器未包含在 ProbeVue 框架中,因此这些限制不会应用这些探测器管理器。

可以通过 SMIT 界面 (使用 "smit probevue" 快速路径) 或直接通过 probevctrl 命令来修改所有 ProbeVue 参数。 如果没有活动的动态跟踪会话,那么可以停止 ProbeVue ,并且可以在停止之后重新启动它,而不需要重新引导。 如果使用线程局部变量的任何会话先前已处于活动状态,那么 ProbeVue 可能无法停止。

下表概述了为动态跟踪会话定义的参数。 在描述中,特权用户指的是超级用户或具有 aix.ras.probevue.trace 权限的用户,而非特权用户指的是没有此权限的用户。

表 2。 动态跟踪会话参数的参数
SMIT 中的描述 最大值 最初配置值上限 最初配置值下限 最小值 关联命令
ProbeVue 框架的最大固定内存 64 GB 可用内存或最大值的 10%(取较小者)。 16 MB 3 MB 分配给 ProbeVue 数据结构的最大固定内存(以 MB 计),包括每个 CPU 的堆栈和每个 CPU 的本地表区域以及所有动态跟踪会话。 这不包括探针管理器分配的任何内存。
注: 虽然可以随时修改此参数,但该值仅在下次启动 ProbeVue 时生效。
每个 CPU 的缺省跟踪缓冲区大小 256 MB 128 KB 8 KB 4 KB 每个 CPU 跟踪缓冲区的缺省大小(以 KB 计)。 对于每个 CPU,ProbeVue 将为每个动态跟踪会话分配两个跟踪缓冲区,一个处于活动状态,在捕获到跟踪数据时由写程序或 Vue 程序使用,另一个处于非活动状态,由阅读器或跟踪使用程序使用。
          例如,在每个 CPU 跟踪缓冲区大小设置为 16K 的 8 路上,ProbeVue 会话的跟踪缓冲区消耗的总内存为 256K。 启动 probevue 命令时,您可以指定另一缓冲区大小(较大或较小),直到它符合会话内存限制。
普通用户会话的最大固定内存 64 GB 2 MB 2 MB 0 MB 为非特权用户的 ProbeVue 会话分配的最大固定内存,包括每个 CPU 跟踪缓冲区的内存。 值 0 将有效地禁用所有非特权用户。 特权用户对其 ProbeVue 会话使用的内存没有限制。 但是,它们仍受允许 ProbeVue 框架使用的最大固定内存的限制。
普通用户的最小跟踪缓冲区读速率 5000 ms 100 ms 100 ms 10 毫秒 非特权用户可请求跟踪使用程序检查跟踪数据的最小期限(以毫秒计)。 此值将在内部舍入到最接近的 10 毫秒倍数值。 特权用户不受此参数限制,但是他们可以指定的最快读速率是 10 毫秒。
跟踪缓冲区的缺省读速率 5000 ms 100 ms 100 ms 10 毫秒 跟踪使用程序将检查内存跟踪缓冲区中的跟踪数据的缺省期限(以毫秒计)。 启动 probevue 命令时您可以指定不同的读速率(较大或较小),直到该值大于最小缓冲区读速率。
常规用户的最大并发会话数 8 1 1 0 非特权用户允许的并行 ProbeVue 会话数。 值零会有效地禁用所有非特权用户。
每个 CPU 计算堆栈的大小 256 KB 20 KB 12 KB 8 KB 发出 Vue 脚本时,ProbeVue 使用的每个 CPU 计算堆栈的大小。 此值将舍入到最接近的 8 KB 倍数值。 ProbeVue 为所有 ProbeVue 会话的每个 CPU 分配一个堆栈。 堆栈使用的内存不包括在每个会话的限制内。
         
注: 虽然可以随时修改此参数,但仅在重建并重新引导 AIX 内核引导映像之后,该值才会生效。 您需要配置 ProbeVue 堆栈以使用 96KB 虚拟内存,才能获得当前目录列表。
每个 CPU 本地表大小的大小 256 KB 32 KB 4 KB 4 KB ProbeVue 为保存自动类的变量和临时变量而使用的每个 CPU 本地表的大小。 ProbeVue 将此区域的一半用于自动变量,将另外一半用于保存临时变量。
          此值总是舍入到最接近的 4 KB 倍数值。 对于每个 CPU,ProbeVue 将分配所有 ProbeVue 会话使用的单个本地表和单个临时表。 本地表使用的内存不包括在每个会话的限制内。
注: 虽然可以随时修改此参数,但该值仅在下次启动 ProbeVue 时生效。
时间间隔探针中允许的最小时间间隔 不适用 1   1 时间间隔调查中对全局 root 用户允许的最小计时器时间间隔(以毫秒计)。
要跟踪的线程数 不适用 32 32 1 ProbeVue 会话在具有线程局部变量时可以支持的最大线程数。 在会话开始时,ProbeVue 框架将线程局部变量分配给使用此属性指定的最大数目的线程。 如果命中具有线程局部变量的探针的线程数超过指定的线程数,那么 ProbeVue 会话会突然停止。
要处理的缺页故障数 1024 0 0 0 用于处理整个框架的缺页故障的缺页故障上下文数目。 缺页故障上下文包含用于保存自动类变量和临时变量的堆栈和本地表。 需要缺页故障上下文才能访问页面调出数据。 如果在发生缺页故障时没有空闲的缺页故障上下文,那么 ProbeVue 不会访存页面调出数据。
在中断上下文中触发时 systrace 探针的最长探针执行时间 不适用 0 0 0 此数字限制在中断上下文中执行的 systrace 探针可能消耗的最长时间(以毫秒计)。 缺省情况下此值为零,这意味着 systrace 探针可以消耗任何长度的时间。
在中断上下文中触发时 io 探针的最长探针执行时间 不适用 0 0 0 此数字限制在中断上下文中执行的 io 探针可能消耗的最长时间(以毫秒计)。 缺省情况下此值为零,这意味着 io 探针可以消耗任何长度的时间。
在中断上下文中触发时 sysproc 探针的最长探针执行时间 不适用 0 0 0 此数字限制在中断上下文中执行的 sysproc 探针可能消耗的最长时间(以毫秒计)。 缺省情况下此值为零,这意味着网络探针可以消耗任何长度的时间。
在中断上下文中触发时网络探针的最长探针执行时间 不适用 0 0 0 此数字限制在中断上下文中执行的网络探针可能消耗的最长时间(以毫秒计)。 缺省情况下此值为零,这意味着网络探针可以消耗任何长度的时间。
网络缓冲区大小上限 64 KB 64 个字节 96 个字节 96 个字节 此值是网络探针管理器针对 bpf 探针点使用的预先分配的缓冲区大小(以字节计)。 第一个 bpf 探针被启用并存在于系统中时将分配此值,直到最后一个 bpf 探针被禁用。 最后一个 bpf 探针类型被禁用时,此缓冲区被释放。 当数据包数据分布在多个数据包缓冲区时,此缓冲区用来复制数据。
异步统计信息访存时间间隔 (以毫秒计) 不适用 1000 毫秒 (1 秒) 1000 毫秒 (1 秒) 100 毫秒 访存异步统计信息的时间间隔 (以毫秒计)。 此值是全局值,适用于所有 ProbeVue 会话。
仅以异步方式访存统计信息 不适用 False False 不适用 指定 ProbeVue ,即使同步方式可用,也必须以异步方式访存统计信息。
在中断上下文中触发时 CPU 绑定时间间隔探测器的最大探测器执行时间。 60 秒 60 秒 100 毫秒 100 毫秒 此数字限制在中断上下文中执行的 CPU 绑定时间间隔探测器可能需要的最大时间 (以毫秒为单位)。 缺省情况下,值为 60secs。

对 ProbeVue 会话进行概要分析

ProbeVue 框架提供概要分析工具,可打开或关闭此工具以估算已启用探针对应用程序的影响。 此工具累积启动探针操作后探针操作所消耗的时间,并在要求时或会话结束时报告。

概要分析报告显示探针字符串及对应该探针字符串的操作消耗的时间。 探针操作消耗的时间以列表形式保留,包括收集数据所消耗的总时间、最短时间、最长时间和平均时间。 概要分析数据还显示对探针操作计时的次数。 如果在概要文件中通过一个探针字符串查找多个函数(通过使用正则表达式或使用 * 替换函数名),那么概要分析数据提供针对所有这类函数启动的探针的累积数据。 它不提供单独探测的函数的计时详细信息,而只提供每个探针操作的相关信息。

BEGINEND 探针操作不是使用此工具进行概要分析的。 这些概要分析详细信息是特定于会话的详细信息。 您可以使用 probevue 命令或 probevctrl 命令随会话启动来启用 probevue 会话概要分析。

有关更多信息,请参阅 probevueprobevctrl 命令。

样本程序

示例 1

以下规范的“Hello World”程序将“Hello World”显示到跟踪缓冲区并退出:

#!/usr/bin/probevue
	
	/* Hello World in probevue */
	/* Program name: hello.e */
	
	@@BEGIN
	{
		printf("Hello World\n");
		exit();
	}

示例 2

当您在键盘上键入 Ctrl-C 时,以下“Hello World”程序将显示“Hello World”:

#!/usr/bin/probevue
	
	/* Hello World 2 in probevue */
	/* Program name: hello2.e */
	
	@@END
	{
		printf("Hello World\n");
	}

示例 3

以下程序显示如何使用线程局部变量。 此 Vue 脚本计算写入特定文件的字节数。 它假定进程都是单线程的或打开文件的线程与写入文件的线程相同。 它还假定所有的写操作都成功。 此脚本可随时终止,并且您可通过在终端键入 Ctrl-C 获取写入的当前字节数。

#!/usr/bin/probevue
	
	/* Program name: countbytes.e */
	int open( char * Path, int OFlag, int mode );
	int write( int fd, char * buf, int sz);
	int done;

	@@syscall:*:open:entry
		when (done != 0 )
	{
		if (get_userstring(__arg1, -1) == "/tmp/foo") {
			thread:trace = 1;	
			done = 1;
		}
	}
	
	@@syscall:*:open:exit
		when (thread:trace)
	{
		thread:fd = __rv;
	}
	
	@@syscall:*:write:entry
		when (thread:trace && __arg1 == thread:fd)
	{
		bytes += __arg3;	/* number of bytes is third arg */ 
	}
	
	@@END
	{
		printf("Bytes written = %d\n", bytes);	
	}

示例 4

以下试探性跟踪程序显示在读取 foo.data 文件时,如何跟踪仅当返回零字节时传送到读系统调用的参数:

#!/usr/bin/probevue
	/* File: ttrace.e */
	/* Example of tentative tracing */
	/* Capture parameters to read system call only if read fails */
	int open ( char* Path, int OFlag , int mode );
	int read ( int fd, char * buf, int sz);
	
	@@syscall:*:open:entry
	{
		filename = get_userstring(__arg1, -1);
		if (filename == "foo.data") {
			thread:open = 1;
			start_tentative("read");
			printf("File foo.data opened\n");
		}
	}
	
	@@syscall:*:open:exit
		when (thread:open == 1)
	{
		  thread:fd = __rv;
		  start_tentative("read");
		  printf("fd = %d\n", thread:fd);
		  thread:open = 0;
	}
		 
	@@syscall:*:read:entry
		when (__arg1 == thread:fd)
	{
		start_tentative("read");
		printf("Read fd = %d, input buffer = 0x%08x, bytes = %d,",
			__arg1, __arg2, __arg3);
		end_tentative("read");
		thread:read = 1;
	}
	
	@@syscall:*:read:exit
		when (thread:read == 1)
	{
		if (__rv < 0) {
			/* The printf below, even though non-tentative, is only
			 * executed in error cases and merges with the 
			 * previously printed tentative data
			 */
			printf(" errno = %d\n", __errno);
			commit_tentative("read");
		}
		else
			discard_tentative("read");
		thread:read = 0;
	}

如果由于将错误的地址(如 0x1000)作为输入缓冲区指针进行传送而导致读取失败,那么可能的输出可能类似于以下输出:

#probevue ttrace.e
File foo.data opened
fd = 4
Read fd = 4, input buffer = 0x00001000, bytes = 256, errno = 14

示例 5

以下 Vue 脚本打印某些内核变量的值并立即退出。 请注意 @@BEGIN 调查中的 exit 函数:

/* File: kernel.e */
/* Example of accessing kernel variables */
/* System configuration structure from /usr/include/sys/systemcfg.h */
struct system_configuration {
	int architecture;	/* processor architecture */
	int implementation;	/* processor implementation */
	int version;		/* processor version */
	int width;		/* width (32 || 64) */
	int ncpus;		/* 1 = UP, n = n-way MP */
	int cache_attrib;	/* L1 cache attributes (bit flags)	*/
				/* bit		0/1 meaning		*/
				/* -------------------------------------*/
				/* 31	 no cache / cache present	*/
				/* 30	 separate I and D / combined    */
	int icache_size;	/* size of L1 instruction cache */
	int dcache_size;	/* size of L1 data cache */
	int icache_asc;		/* L1 instruction cache associativity */
	int dcache_asc;		/* L1 data cache associativity */
	int icache_block;	/* L1 instruction cache block size */
	int dcache_block;	/* L1 data cache block size */
	int icache_line;	/* L1 instruction cache line size */
	int dcache_line;	/* L1 data cache line size */
	int L2_cache_size;	/* size of L2 cache, 0 = No L2 cache */
	int L2_cache_asc;	/* L2 cache associativity */
	int tlb_attrib;		/* TLB attributes (bit flags)		*/
				/* bit		0/1 meaning		*/
				/* -------------------------------------*/
				/* 31	 no TLB / TLB present		*/
				/* 30	 separate I and D / combined    */
	int itlb_size;		/* entries in instruction TLB */
	int dtlb_size;		/* entries in data TLB */
	int itlb_asc;		/* instruction tlb associativity */
	int dtlb_asc;		/* data tlb associativity */
	int resv_size;		/* size of reservation */
	int priv_lck_cnt;	/* spin lock count in supevisor mode */
	int prob_lck_cnt;	/* spin lock count in problem state */
	int rtc_type;		/* RTC type */
	int virt_alias;		/* 1 if hardware aliasing is supported */
	int cach_cong;		/* number of page bits for cache synonym */
	int model_arch;		/* used by system for model determination */
	int model_impl;		/* used by system for model determination */
	int Xint;		/* used by system for time base conversion */
	int Xfrac;		/* used by system for time base conversion */
	int kernel;		/* kernel attributes			    */
				/* bit		0/1 meaning		    */
				/* -----------------------------------------*/
				/* 31	32-bit kernel / 64-bit kernel	    */
                                /* 30   non-LPAR      / LPAR                */
                                /* 29   old 64bit ABI / 64bit Large ABI     */
                                /* 28   non-NUMA      / NUMA                */
                                /* 27   UP            / MP                  */
                                /* 26   no DR CPU add / DR CPU add support  */
                                /* 25   no DR CPU rm  / DR CPU rm  support  */
                                /* 24   no DR MEM add / DR MEM add support  */
                                /* 23   no DR MEM rm  / DR MEM rm  support  */
                                /* 22   kernel keys disabled / enabled	    */
                                /* 21   no recovery   / recovery enabled    */
                                /* 20   non-MLS    / MLS enabled	    */
	long long physmem;	/* bytes of OS available memory		    */
	int slb_attr;		/* SLB attributes			    */
				/* bit		0/1 meaning		    */
				/* -----------------------------------------*/
				/* 31		Software Managed	    */
	int slb_size;		/* size of slb (0 = no slb)		    */
	int original_ncpus;	/* original number of CPUs		    */
	int max_ncpus;		/* max cpus supported by this AIX image     */
	long long maxrealaddr;	/* max supported real memory address +1     */
	long long original_entitled_capacity;
				/* configured entitled processor capacity   */
				/* at boot required by cross-partition LPAR */
				/* tools.				    */
	long long entitled_capacity; /* entitled processor capacity	    */
	long long dispatch_wheel; /* Dispatch wheel time period (TB units)  */
	int capacity_increment;	/* delta by which capacity can change	    */
	int variable_capacity_weight;	/* priority weight for idle capacity*/
					/* distribution			    */
	int splpar_status;	/* State of SPLPAR enablement		    */
				/*	0x1 => 1=SPLPAR capable; 0=not	    */
				/*	0x2 => SPLPAR enabled 0=dedicated;   */
				/*			     1=shared       */
	int smt_status;		/* State of SMT enablement                  */
				/*    0x1 = SMT Capable  0=no/1=yes         */
				/*    0x2 = SMT Enabled  0=no/1=yes         */
				/*    0x4 = SMT threads bound true 0=no/1=yes */
	int smt_threads;	/* Number of SMT Threads per Physical CPU   */
        int vmx_version;        /* RPA defined VMX version, 0=none/disabled */
	long long sys_lmbsize;	/* Size of an LMB on this system. */
	int num_xcpus;		/* Number of exclusive cpus on line */
	signed char errchecklevel;/* Kernel error checking level */
	char pad[3];		/* pad to word boundary		*/
        int dfp_version;        /* RPA defined DFP version, 0=none/disabled */
				/* if MSbit is set, DFP is emulated         */
};

__kernel struct system_configuration _system_configuration;

@@BEGIN
{
	String s[40];
	int j;
	__kernel int max_sdl;	/* Atomic RAD system decomposition level */
	__kernel long lbolt;	/* Ticks since boot  */

	printf("No. of online CPUs\t\t= %d\n", _system_configuration.ncpus);

	/* Print SMT status */
	printf("SMT status\t\t\t=");
	if (_system_configuration.smt_status == 0)
		printf(" None");
	else {
		if (_system_configuration.smt_status & 0x01)
			printf(" Capable");
		if (_system_configuration.smt_status & 0x02)
			printf(" Enabled");
		if (_system_configuration.smt_status & 0x04)
			printf(" BoundThreads");
	}
	printf("\n");

	/* Print error checking level */
	if (_system_configuration.errchecklevel == 1)
		s = "Minimal";
	else if (_system_configuration.errchecklevel == 3)
		s = "Normal";
	else if (_system_configuration.errchecklevel == 7)
		s = "Detail";
	else if (_system_configuration.errchecklevel == 9)
		s = "Maximal";
	printf("Error checking level\t\t= %s\n",s);

	printf("Atomic RAD system detail level\t= %d\n", max_sdl);

	/* Long in the kernel is 64-bit, so we use %lld below */
	printf("Number of ticks since boot\t= %lld\n", lbolt);

	exit();
}

在具有缺省内核属性的 Power 5 专用分区上运行上述脚本时,以下输出是可能的输出:

# probevue kernel.e
No. of online CPUs              = 4
SMT status                      = Capable Enabled BoundThreads
Error checking level            = Normal
Atomic RAD system detail level  = 2
Number of ticks since boot      = 34855934