谓词

如果必须有条件地执行探针点处的子句,那么您无法使用谓词。 谓词部分由紧跟在调查规范部分之后显示的 when 关键字标识。 谓词本身包含常规的使用双括号的 C 语言格式条件表达式。

对谓词部分中的表达式有一些限制:

  • 在谓词中不允许使用内核类变量。
  • 在谓词中不允许使用自动类变量。
  • 在谓词中不允许使用浮点类型变量。
  • 在谓词中不允许使用 Vue 函数。
  • 在谓词中不允许产生副作用,因此不允许“=”赋值运算符及其派生符号,如 +=|= 等。
  • 在谓词中不允许使用传送到函数的第 9 个和之后的参数(入口类变量 __arg9__arg10 等)。

通过使用 if ... ,可以有条件地执行子句中的特定操作。 else 语句,其工作方式类似于 C 中的类似语句。 但是,如果要有条件地发出整个子句,那么最好改为使用谓词,因为 ProbeVue 旨在优化谓词的执行。

注: 当探针点可以针对多个进程触发时,在谓词中使用线程局部变量是降低启用探针的总体性能影响的绝佳方法。 在谓词中设置有条件的检查比使用 if 语句更好。

以下脚本在谓词中使用线程局部变量来有效地检测何时将特定的字符串写入特定文件中。 它还显示将子句的操作块中的 if 语句与谓词配合使用的一个示例。 文件名和字符串都会作为参数传送到使用 shell 位置参数的脚本。

/*
 * Filename : chkfilewrite.e
 *
 * Capture when someone writes a particular word to a specific file 
 * takes 2 arguments: filename and word
 *
 * assumes file name is < 128
 *
 * Usage: probevue chkfilewrite.e \"<filename>\" \"<string>\"
 *
 *	The backslashes above are necessary to prevent shell
 *	from stripping the double quotation mark.
 */

int open(char *fname, int m, int p);
int write(int fd, char *s, int size);

@@syscall:*:open:entry
{
	__auto String fname[128];

	fname = get_userstring(__arg1, -1);

	if (fname == $1)
		thread:opening = 1;
}

@@syscall:*:open:exit
	when (thread:opening == 1)
{
	thread:fd = __rv;
	thread:opening = 0;

}

@@syscall:*:write:entry
	when (thread:fd == __arg1)
{
	__auto String buf[128];

	if (__arg3 < 128)
		buf = get_userstring(__arg2, __arg3);
	else
		buf = get_userstring(__arg2, 128);

	if (strstr(buf, $2)) {
		printf("%d wrote word to file.\n", __pid);
		exit();
	}
}

要运行此程序以检查何时有人将字符串“Error”写入 foo.log 文件,您可以发出以下命令:

probevue chkfilewrite.e \"foo.log\" \"Error\"
注: 您可以通过添加 close 探测器来增强先前的脚本,以检测关闭文件的时间,从而防止在关闭原始文件并打开新文件并复用同一文件描述符号之后脚本捕获词。