systemtap学习笔记及疑问

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.

没有更多推荐了,返回首页