- 使用自己的脚本处理数据
- perf record-e kmem:kmalloc-e raw_syscalls:sys_enter ls/
- perf script-g perl
- perf script event handlers, generated by perf script-g perl
- Licensed under the terms of the GNU GPL License version 2
- The common_*event handler fields are the most useful fields common to
- all events.They don't necessarily correspond to the'common_*'fields
- in the format files.Those fields not available as handler params can
- be retrieved using Perl functions of the form common_*($context).
- See Context.pm for the list of available functions.
- optional
- optional
- perf script-s kmalloc-syscall.pl
使用自己的脚本处理数据
有时我们会打算自己写脚本来实现事件的统计处理,而不是执行现存的脚本。perf script考虑这样的需求,准备了根据记录的事件生成脚本模型的功能。
下面查看一个用来调查系统调用和内核中分配内存的kmalloc()关系的脚本实例。首先生成使用perf record记录必要事件的数据文件。
perf record-e kmem:kmalloc-e raw_syscalls:sys_enter ls/
bin dev home lib32 media opt root selinux sys tracing var
boot etc lib lib64 mnt proc sbin srv tmp usr
[perf record:Woken up 1 times to write data]
[perf record:Captured and wrote 0.037 MB perf.data(~1633 samples)]
然后,向perf script传递-g选项,根据数据文件生成脚本的模型。-g选项将生成的脚本语言(当前为Perl或Python)作为参数。在下例中,生成的是perf脚本。
perf script-g perl
generated Perl script:perf-script.pl
生成的脚本直接就具有显示事件内容的功能。
perf script event handlers, generated by perf script-g perl
Licensed under the terms of the GNU GPL License version 2
The common_*event handler fields are the most useful fields common to
all events.They don't necessarily correspond to the'common_*'fields
in the format files.Those fields not available as handler params can
be retrieved using Perl functions of the form common_*($context).
See Context.pm for the list of available functions.
use lib"$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
use lib"./Perf-Trace-Util/lib";
use Perf:Trace:Core;
use Perf:Trace:Context;
use Perf:Trace:Util;
sub trace_begin
{
optional
}
sub trace_end{
optional
}
sub raw_syscalls:sys_enter
{
my($event_name,$context,$common_cpu,$common_secs,$common_nsecs,
$common_pid,$common_comm,
$id,$args)=@_;
print_header($event_name,$common_cpu,$common_secs,$common_nsecs,
$common_pid,$common_comm);
printf("id=%d, args=%s\n",
$id,$args);
}
sub kmem:kmalloc
{
my($event_name,$context,$common_cpu,$common_secs,$common_nsecs,
$common_pid,$common_comm,
$call_site,$ptr,$bytes_req,$bytes_alloc,
$gfpflags)=@;
print_header($event_name,$common_cpu,$common_secs,$common_nsecs,
$common_pid,$common_comm);
printf("call_site=%u, ptr=%u, bytes_req=%u, bytes_alloc=%u,".
"gfp_flags=%s\n",
$call_site,$ptr,$bytes_req,$bytes_alloc,
flag_str("kmem:kmalloc","gfp_flags",$gfp_flags));
}
sub trace_unhandled
{
my($event_name,$context,$common_cpu,$common_secs,$common_nsecs,
$commonpid,$common_comm)=@;
print_header($event_name,$common_cpu,$common_secs,$common_nsecs,
$common_pid,$common_comm);
}
sub print_header
{
my($eventname,$cpu,$secs,$nsecs,$pid,$comm)=@;
printf("%-20s%5u%05u.%09u%8u%-20s",
$event_name,$cpu,$secs,$nsecs,$pid,$comm);
}
从生成的脚本的内容,可以看出是事件触发类型的程序,perf script依次处理事件,然后将信息传递给与事件名称相对应的函数。通过更改处理这个事件的函数的内容,可以执行任意的处理。例如,要统计哪个系统调用调用了几次kmalloc(),可以将生成的脚本修改为如下内容。
use lib"$ENV{'PERF_EXEC_PATH'}/scripts/perl/Perf-Trace-Util/lib";
use lib"./Perf-Trace-Util/lib";
use Perf:Trace:Core;
use Perf:Trace:Context;
use Perf:Trace:Util;
@count=();
$current_id=-1;
sub trace_end
{
for($id=0;$id<1024;$id++){
if(@count[$id]!=0){
printf("syscall%d invokes kmalloc%d times.\n",
$id,@count[$id]);
}
}
}
sub raw_syscalls:sys_enter
{
my($event_name,$context,$common_cpu,$common_secs,$common_nsecs,
$common_pid,$common_comm,
$id,$args)=@_;
$current_id=$id;
}
sub kmem:kmalloc
{
my($event_name,$context,$common_cpu,$common_secs,$common_nsecs,
$common_pid,$common_comm,
$call_site,$ptr,$bytes_req,$bytes_alloc,
$gfpflags)=@;
if($current_id!=-1){
@count[$current_id]++;
}
}
将这个脚本另存为kmalloc-syscall.pl,并使用perf script来尝试运行。
perf script-s kmalloc-syscall.pl
syscall 0 invokes kmalloc 1 times.
syscall 2 invokes kmalloc 25 times.
syscall 9 invokes kmalloc 16 times.
syscall 10 invokes kmalloc 16 times.
syscall 21 invokes kmalloc 9 times.
syscall 137 invokes kmalloc 1 times.
可以像这样使用现有的脚本语言非常简单地记述事件的处理方式,就是perf script的特点。从这个功能也可以使用Hack#71介绍的通过perf probe生成的事件,因此实质上也就是可以使用脚本来处理内核中的大部分信息。