2. trace event简介

1,681 阅读5分钟

1. 参考资料

pwl999 trace event的使用

2. trace event简介

trace event框架是使用tracepoints来创建的,而不需要使用创建模块来注册probe函数。不是所有的tracpoint都能够使用trace event框架。内核开发者必须提供代码定义信息怎么保存到tracing buffer、以及信息怎么打印出来。

一个tracepoint可以理解为一个linux内核中的占位符函数,内核子系统的开发者常常用它们来debug。static表明这些tracepoint的位置是固定的,你可以把它理解位传统C程序中的 #if DEBUG部分。如果在运行时没有开启,它们是不占用任何系统开销的。

# 查看当前支持的跟踪事件列表
cat /sys/kernel/debug/tracing/available_events 
# 目前内核支持1493个events
wc -l available_events 
1493 available_events

所有有效的trace event同时会在“/sys/kernel/debug/tracing/events/”层次文件夹中列出,主要有如下类别:

image.png

3. 使能sched_wakeup event

启用特定event,如‘sched_wakeup’,例如:

cd /sys/kernel/debug/tracing/events
echo 0 > trace
echo 1 > tracing_on
# 需要使用‘>>’,否则会首先disable所有的events
echo sched_wakeup >> set_event
# enable event ‘sched_wakeup’:
echo 1 > events/sched/sched_wakeup/enable
cat trace

image.png

Disable event:在echo event name到set_event之前设置一个'!'前缀

echo '!sched_wakeup' >> set_event

events被组织成subsystems,类似ext4, irq, sched等等。一个subsystem中所有的events可以通过"subsystem name:*"语法来表示。例如:enable所有的irq event

echo 'irq:*' > set_event

enable sched subsystem中所有的events:

echo 1 > events/sched/enable

enable所有的events:

echo 1 > events/enable

为了早期启动时调试,可以使用以下boot选项:

trace_event=[event-list]

event-list是逗号分隔的event列表。

4. 事件过滤

4.1 Event filtering语法

一个filter expression由多个组成,它们使用逻辑操作符 ‘&&’、‘||’组合在一起。

# filter的字段名 field-name可以在对应event的‘format’文件中查看
# relational-operators依赖于需要测试的字段类型(数字/字符串等)
field-name relational-operator value
  • 数字类的操作符包括:

==, !=, <, <=, >, >=, &

  • 字符类的操作符包括:

==, !=, ~

  • 约等于操作符(~)接受通配符形式 (*,?)和字符类 ([)。举例:

prev_comm ~ "ba*sh"

4.2 Setting filters

通过将filter expressions写入给定event的filter文件,来设置单个event的filter。

cd /sys/kernel/debug/tracing/events/signal/signal_generate
echo "((sig >= 10 && sig < 15) || sig == 17) && comm != bash" > filter

如果表达式中存在错误,则在设置时会得到一个“Invalid argument”错误,错误的字符串连同错误消息可以通过查看过滤器来查看,例如:

# cd /sys/kernel/debug/tracing/events/signal/signal_generate
# echo "((sig >= 10 && sig < 15) || dsig == 17) && comm != bash" > filter
-bash: echo: write error: Invalid argument
# cat filter
((sig >= 10 && sig < 15) || dsig == 17) && comm != bash
^
parse_error: Field not found

目前,错误的插入符号(‘^’)总是出现在过滤器字符串的开头;即使没有更精确的位置信息,错误消息仍然应该是有用的。

例如上面的sched_wakeup的例子:

cd events/sched/sched_wakeup
# 过滤comm为gnome-terminal的进程
echo 'comm ~ "gnome-terminal*"' > filter
cd /sys/kernel/debug/tracing/events
echo 0 > trace
cat trace

image.png

4.3 Clearing filters

清除某个event的filter,echo 0 到对应event的filter文件。

清除某个subsystem中所有events的filter,echo 0 到对应subsystem的filter文件。

4.4 PID filtering

/sys/kernel/debug/tracing文件夹下的set_event_pid 文件,可以给所有event配置PID过滤:

# 只追踪当前进程
cd /sys/kernel/debug/tracing
echo $$ > set_event_pid
echo 1 > events/enable

# 追加PID使用 ‘>>’
echo 123 244 1 >> set_event_pid

5. Event triggers

跟踪事件可以有条件地调用trigger ‘commands’,它可以enabling or disabling其他trace event,或者在trace event命中时调用stack trace。每当调用具有附加触发器的trace event时,就会调用与该event相关联的 trigger commands。

将触发表达式写入给定event的“trigger”文件,triggers将会从event上增加或者移除。

任何给定的触发器还可以具有与它相关联的事件过滤中描述的相同形式的事件过滤器。如果调用的事件通过关联的过滤器,则该命令将被调用。如果没有与触发器关联的过滤器,它总是通过。

# 使用echo command 到‘trigger’文件的形式来增加Trigger:
echo 'command[:count] [if filter]' > trigger
# 移除Trigger使用同样的命令,但是加上了 ‘!’ 前缀:
echo '!command[:count] [if filter]' > trigger

在移除trigger时 [if filter]部分不参与匹配,所以可以让其在‘! command’中缺失也可以完成同样的功能。filter部分的语法和上一节 ‘Event filtering’ 中描述的相同。为了方便使用,当前filter只支持使用‘>’增加或删除单条trigger,没有明确的 ‘>>’ 支持(实际上‘>’的作用就相当于‘>>’)或者截短支持移除所有的trigger(必须使用‘!’命令逐条移除)。

trigger支持以下命令:

5.1 enable_event/disable_event

当triggering event被命中时,这些命令可以enable or disable其他的trace event。当这些命令被注册,其他的trace event变为active,但是在“soft” mode下disable。这时,tracepoint会被调用但是不会被trace。这些event tracepoint一直呆在这种模式中直到trigger被触发。

举例,以下的trigger导致kmalloc events被trace当一个read系统调用进入,:1 表明该行为只发生一次:

echo 'enable_event:kmem:kmalloc:1' > events/syscalls/sys_enter_read/trigger
echo 1 > events/syscalls/sys_enter_read/enable

image.png

以下的trigger导致kmalloc events被disable当一个read系统调用退出,每次退出都会调用:

echo 'disable_event:kmem:kmalloc' > events/syscalls/sys_exit_read/trigger

命令格式如下:

enable_event:<system>:<event>[:count]
disable_event:<system>:<event>[:count]

移除命令:

echo '!enable_event:kmem:kmalloc:1' > events/syscalls/sys_enter_read/trigger
echo '!disable_event:kmem:kmalloc' > events/syscalls/sys_exit_read/trigger

注意:每个 triggering event可以有任意多个触发动作,但是每种触发动作只能有一个。例如,sys_enter_read可以触发enable kmem:kmalloc和sched:sched_switch,但是kmem:kmalloc不能有两个版本kmem:kmalloc and kmem:kmalloc:1或者是‘kmem:kmalloc if bytes_req == 256’ and ‘kmem:kmalloc if bytes_alloc == 256’(他们组合成单个filter在kmem:kmalloc event中)。

5.2 stacktrace

这个命令在trace buffer中dump出堆栈调用,在triggering event发生时。

举例,以下的trigger dump出堆栈调用,在每次kmalloc tracepoint被命中:

echo 'stacktrace' >events/kmem/kmalloc/trigger

移除命令:

echo '!stacktrace' >events/kmem/kmalloc/trigger
5.3 snapshot

当block request queue被unplugged并且depth > 1,创建一个snapshot。

echo 'snapshot if nr_rq > 1' > events/block/block_unplug/trigger
5.4 traceon/traceoff

把整个trace tracing on/off当event被命中。在block request queue第一次unplugged并且depth > 1,以下命令将 turns tracing off 。

echo 'traceoff:1 if nr_rq > 1' > events/block/block_unplug/trigger
5.5 hist

组合触发,这个命令聚合多个trace event的字段到一个hash表中。查看Documentation/trace/histogram.txt获取更多的细节和用例。