您的位置:首页 > 其它

systemtap学习笔记及疑问

2012-07-21 10:22 369 查看
1.如何在命令行传递给脚本参数?

在testsuit的例子里,eventcount.stp脚本给出了一种很好的方式:

#!/usr/bin/stap

global c

probe %($# == 0 || $# > 32 %? begin %: never %)
{
printf("Please specify between 1 and 32 events to count.\n")
exit()
}

//paramaterize up to 32 arguments
probe %($# >= 1 %? $1 %: never %),
%($# >= 2 %? $2 %: never %),
%($# >= 3 %? $3 %: never %),
%($# >= 4 %? $4 %: never %),
%($# >= 5 %? $5 %: never %),
%($# >= 6 %? $6 %: never %),
%($# >= 7 %? $7 %: never %),
%($# >= 8 %? $8 %: never %),
%($# >= 9 %? $9 %: never %),
%($# >= 10 %? $10 %: never %),
%($# >= 11 %? $11 %: never %),
%($# >= 12 %? $12 %: never %),
%($# >= 13 %? $13 %: never %),
%($# >= 14 %? $14 %: never %),
%($# >= 15 %? $15 %: never %),
%($# >= 16 %? $16 %: never %),
%($# >= 17 %? $17 %: never %),
%($# >= 18 %? $18 %: never %),
%($# >= 19 %? $19 %: never %),
%($# >= 20 %? $20 %: never %),
%($# >= 21 %? $21 %: never %),
%($# >= 22 %? $22 %: never %),
%($# >= 23 %? $23 %: never %),
%($# >= 24 %? $24 %: never %),
%($# >= 25 %? $25 %: never %),
%($# >= 26 %? $26 %: never %),
%($# >= 27 %? $27 %: never %),
%($# >= 28 %? $28 %: never %),
%($# >= 29 %? $29 %: never %),
%($# >= 30 %? $30 %: never %),
%($# >= 31 %? $32 %: never %),
%($# >= 32 %? $32 %: never %)
{
totalc <<< 1
if (target() && ! target_set_pid(pid()))
next
filteredc <<< 1
c[sprintf("%s(%d)",execname(),tid()), pn()]<<<1
}

global totalc, filteredc

probe begin {
start_ms = gettimeofday_ms()
if (target()) msg = sprintf ("pid %d + children", target())
else msg = "unfiltered";
printf("Starting event counting at %s, %s\n",
tz_ctime(gettimeofday_s()), msg)
}
global start_ms

probe end {
printf("Finished event counting at %s.\n", tz_ctime(gettimeofday_s()))
elapsed_ms = gettimeofday_ms() - start_ms
if (elapsed_ms < 0) elapsed_ms=1
printf("Total time elapsed: %d ms, %d events total, %d filtered.\n",
elapsed_ms, @count(totalc), @count(filteredc))

printf("%-25s %-30s %s\n", "TID", "EVENT", "COUNT (RATE Hz)")
printf("%-25s %-30s %s\n", "---", "-----", "---------------")
foreach([tid+, name] in c)
printf("%-25s %-30s %d (%d.%02d)\n", tid, name,
@count(c[tid, name]),
(@count(c[tid,name])*100000/elapsed_ms)/100,
(@count(c[tid,name])*100000/elapsed_ms)%100)
}


你可以在命令行中输入:

sudo stap eventcount.stp syscall.open syscall.close syscall.read syscall.write

2.疑问????

21	probe kernel.function("inode_permission@fs/namei.c").return !,
//感叹号是什么意思?
22	      kernel.function("permission@fs/namei.c").return
23	{
24	  if (!$return && squash_inode_permission[tid()])
//这个return 应该是那个probe的return
25	    $return = -13 # -EACCES (Permission denied)
26	  delete squash_inode_permission[tid()]
27	}


这个是脚本badname.stp中的内容。。。。
3.脚本中的不同的probe的执行次序问题:

# Array to hold the list of drop points we find
global locations
# Note when we turn the monitor on and off
probe begin { printf("Monitoring for dropped packets\n") }
probe end { printf("Stopping dropped packet monitor\n") }
# increment a drop counter for every location we drop at
probe kernel.trace("kfree_skb") { locations[$location] <<< 1 }
# Every 5 seconds report our drop locations
probe timer.sec(5)
{
printf("\n")
foreach (l in locations-) {
printf("%d packets dropped at %s\n",
@count(locations[l]), symname(l))
}
delete locations
}


上面这个脚本中,可以看到probe end是第二个probe,是不是意味着下面的probe不会被执行呢?

当然不是,probe end只有在遇到Ctrl+C或者exit()时才会执行,而且,每个probe相当于一个监视模块,因此彼此之间相对比较独立,跟各个probe的顺序的关系不是很大。

4. 在testsuit中有para-callgraph.stp脚本,疑点如下:

%( $# > 1 %? if (tid() in trace) %)

$#是什么意思?(表示的是命令行中给出的参数的个数)
如果$#>1, 紧接着判断if(tid() in trace)...

5.

stap 命令行传递过来的字面值

字符值要么是由引号包含的字符串,要么是整数。关于整数的信息,请参阅 5.2.2 节,而字符

串的信息,请参阅 5.2.3 节。

命令行后面的脚本参数被扩展为字面值,可将它用于所有接受字面值的上下文中,但引用不存

在的参数编号将引致错误。

5.7.1 $1 ... $<NN> 将参数转换成整数

使用$1 ... $<NN> 将命令行参数转换成整数字面值。

@1 ... @<NN> 将参数转换成字符串

@1 ... @<NN> 将命令行参数转换成字符串字面值。

以下述为例,假定该脚本的名字为 example.stp

probe begin { printf("%d, %s/n", $1, @2) }

运行如下:

# stap example.stp 10 mystring

那么,$1 会被替换成 10 ,而@2 会被替换成"mystring" ,结果输出:

10, mystring

6.

打印目标变量

在.return中打印return值

printf("return = %d", $$return);注意,这个只能在.return中使用

syscall.fork中打印传递进来的参数的值:

printf("%s\n", $$parms);

但是如何打印函数中指定的变量的值?

printf("trace = %d\n", $trace);

As code evolves the target variables available may change. The @defined makes it easier to handle

those variations in the available target variables. The @defined provides a test to see if a particular

target variable is available. The result of this test can be used to select the appropriate expression

但是,有的时候会出现找不到指定变量的情况,这个是systemtap的原因。。。

printf("%s", $$locals);这个会将函数中所有的变量的值打印,注意这个是运行到该行时探寻到的变量的值。

如何插桩到函数的指定行?

probe kernel.statement("do_fork@kernel/fork.c+30");这样就在do_fork+30行处插入了一个桩

7.

/**

* sfunction kernel_string - Retrieves string from kernel memory

* @addr: The kernel address to retrieve the string from

*

* Description: This function returns the null terminated C string

* from a given kernel memory address. Reports an error on string

* copy fault.

*/

8.
@hist_log可以打印你存储在static aggregate类型中数据(参见脚本deviceseeks.stp)

9.

在blk_stat.stp脚本中用到了@entry()操作:

A new operator, @entry, is available for automatically saving an expression at entry time for use in a .return probe.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息