脚本变量

脚本变量是自动、线程局部或全局类变量。

脚本变量仅存在于 Vue 脚本的上下文中,并且它们的值是从脚本中指定的。 而且,只能从定义这些变量的脚本中对它们进行访问或修改。

通常,您必须通过声明语句显式声明脚本变量的数据类型。 但是,在某些受限的情况下,如果对变量进行首次引用的是赋值运算且变量位于赋值运算符的左侧,那么编译器会隐式确定程序变量的数据类型。

整数类型的隐式类型确定

要指定为整数类型,赋值运算的右侧必须是以下其中一种情况:

  • 常数。
  • 另一个整数类型的变量,包括内置变量。 从类型未知的变量进行指定是错误的。
  • 返回整数类型 (如 diff_time 函数) 的 Vue 函数。
  • 将右侧的表达式强制转换为整数类型,虽然某些情况下,这样做可能会产生警告。
  • 包括上述任何一种情况的表达式。

变量根据右侧的表达式采用相应的类型和值。 另外,可通过将变量类作为变量的前缀为该变量指定变量类。 以下脚本演示了一些示例:

/*
 * File:	implicit2.e
 * Usage:	Demonstrates implicit assignment for integer types 
 */

int read(int fd, char *p, long size);

@@BEGIN
{
	count = 404;			/* count: int of global class */
	zcount = 2 * (count - 4);	/* zcount: int of global class */
	llcount = 33459182089021LL;  	/* lcount: long long of global class */
	lxcount = 0xF00000000245B20LL;	/* xcount: long long of global class */

}

@@syscall:$1:read:entry
{
	__auto probev_timestamp_t ts1, ts2;
	int gsize;
	ts1 = timestamp();
	auto:dcount = llcount - lxcount;  /* dcount: long long of auto class */ 

	auto:mypid = __pid;	/* mypid:  pid_t (64-bit integer) of automatic class */
	fd = __arg1;		/* fd: int of global class */

	/* The following cast will likely cause a compiler warning
	 * but can be ignored here
	 */
	global:bufaddr = (long)__arg2;	/* bufaddr: long of global class */

	gsize = __arg3;
	thread:size =  gsize + 400;	/* size: int of thread-local class */

	printf("count = %d, zcount = %lld\n", count, zcount);
	printf("llcount = %lld, lxcount = 0x%016llx, diff = %lld\n",
			llcount, lxcount, dcount);
	printf("mypid = %ld, fd = %d, size = %d\n", mypid, fd, size);
	printf("bufaddr = 0x%08x\n", bufaddr);
	ts2 = timestamp();
	
	auto:diff = diff_time(ts1, ts2, MICROSECONDS);	/* diff: int of automatic class */
	
	printf("Time to execute = %d microseconds\n", diff);
	
	exit();
}
注: 前面的脚本中存在类似 shell 位置的参数,即 @@syscall:$1:read:entry 探测器规范中的 $1 符号。 syscall 探针管理器允许在第二个字段中使用进程标识,以表明必须只为特定的进程启用系统调用探针点。 在此脚本中,没有对特定的进程标识进行硬编码,而是将第二个字段设为 shell 位置参数,从而允许在发出脚本时将实际的进程标识作为参数进行传送。 probevue 命令会将脚本中的任何 shell 位置参数替换为在命令行上传送的相应参数。

假定您要调查进程标识为 250000 的进程,那么以下脚本显示了运行 implicit2.e 脚本的示例。

# probevue implicit2.e 250000
WRN-100: Line:29 Column:26 Incompatible cast
count = 404, zcount = 800
llcount = 33459182089021, lxcount = 0x0f00000000245b20, diff = -1080830451389212643
mypid = 250000, fd = 10, size = 4496
bufaddr = 0x20033c00
Time to execute = 11 microseconds

在上述示例中,脚本中的 $1 符号会自动替换为“250000”,因此会将 read 系统调用入口探针点限制为进程标识为 250000 的进程。

字符串类型的隐式类型确定

要指定为字符串类型,赋值运算的右侧必须是以下其中一种情况:

  • 字符串文字,它是括在双引号中的字符序列。
  • 另一个字符串类型的变量,包含内置变量。
  • 返回类似于 et_userstring 函数的字符串的 Vue 函数。
  • 包括上述任何一种情况的表达式。

以下示例演示如何指定隐式字符串类型:

/*
 * File:	implicit3.e
 * Usage:	Demonstrates implicit assignment for string types 
 */

int write(int fd, char *p, long size);

@@BEGIN
{
	s1 = "Write system call:\n";
}

@@syscall:$1:write:entry
{
	String s2[40];
	
	wbuf = get_userstring(__arg2, __arg3);

	s2 = s1;

	zbuf = s2;

	pstring = zbuf + wbuf;

	printf("%s\n", pstring);
}

@@syscall:$1:write:exit
{
	ename = __pname;
	printf("Exec name = %s\n", ename);
	exit();
}

发出进程标识以替换 $1 shell 位置参数变量时必须将该进程标识作为参数传送到脚本。

列表类型的隐式类型确定

要指定为列表类型,赋值运算的右侧必须是 list() 函数。 任何子句都支持 list() 函数。