编辑
2025-01-22
记录知识
0
请注意,本文编写于 156 天前,最后修改于 59 天前,其中某些信息可能已经过时。

目录

一、events目录
二、示例使用
2.1 enable
2.2 format
2.3 id
2.4 filter
2.5 trigger
2.5.1 traceon
2.5.2 traceoff
2.5.3 stacktrace
2.5.4 enable_event
2.5.5 disable_event

系统中存在很多linux内核默认预设的trace events,其目的是方便大家查相同问题时能够复用他们的tracepoint,基于此,本文章根据linux内核现成的trace event做分享,主要聊聊如何使用人家定义好的event,从而方便大家调试问题

一、events目录

trace events的目录如下:

# ls /sys/kernel/debug/tracing/events/ alarmtimer fib6 namei sched android_fs filelock napi scmi asoc filemap neigh signal avc ftrace net skb binder gadget nfs smbus block gpio nfs4 sock bpf_test_run header_event nfsd spi bpf_trace header_page nvme sunrpc bridge hwmon oom swiotlb btrfs i2c pagefault sync_trace cfg80211 initcall page_isolation task cgroup iomap pagemap tcp cifs iommu page_pool thermal clk io_uring percpu thermal_ipa_power cma ipi power thermal_power_allocator compaction irq printk timer cpufreq_interactive jbd2 pwm udp cpuhp kmem qdisc v4l2 devfreq kvm ras vb2 dma_fence kyber raw_syscalls virtio_gpu drm mac80211 rcu vmscan dwc3 mali regmap workqueue emulation mdio regulator writeback enable migrate rpcgss xdp error_report mmap rpm xfs ext4 mmc rseq xhci-hcd fib module rtc

我们可以看到linux提供了107个trace system,我们在查问题的时候可以先考虑这些trace system

这里还是以经典函数block_rq_complete为例,可以看到其内容如下:

# find /sys/kernel/debug/tracing/events/block/block_rq_complete/ /sys/kernel/debug/tracing/events/block/block_rq_complete/ /sys/kernel/debug/tracing/events/block/block_rq_complete/format /sys/kernel/debug/tracing/events/block/block_rq_complete/trigger /sys/kernel/debug/tracing/events/block/block_rq_complete/filter /sys/kernel/debug/tracing/events/block/block_rq_complete/id /sys/kernel/debug/tracing/events/block/block_rq_complete/enable

二、示例使用

关于trace evemt的文章,可以查看内核官方文档如下,这里就不按照文档重复讨论了:

https://www.kernel.org/doc/html/latest/trace/events.html

本章主要聚焦在下面这几个文件的使用上:

enable filter format id trigger

2.1 enable

顾名思义,这个就是打开此event的事件,方法如下:

echo 1 > enable

这里和tracepoint基础编程介绍有点重复,就无需展开了。

2.2 format

这里能够查看这个event的格式,我们在tracepoint基础编程介绍可以知道定义一个TRACE_EVENT需要包含五要素:name/prototype/args/struct/assign/print,这里是具体展现。如下示例:

# cat format name: block_rq_complete ID: 1350 format: field:unsigned short common_type; offset:0; size:2; signed:0; field:unsigned char common_flags; offset:2; size:1; signed:0; field:unsigned char common_preempt_count; offset:3; size:1; signed:0; field:int common_pid; offset:4; size:4; signed:1; field:dev_t dev; offset:8; size:4; signed:0; field:sector_t sector; offset:16; size:8; signed:0; field:unsigned int nr_sector; offset:24; size:4; signed:0; field:int error; offset:28; size:4; signed:1; field:char rwbs[8]; offset:32; size:8; signed:0; field:__data_loc char[] cmd; offset:40; size:4; signed:0; print fmt: "%d,%d %s (%s) %llu + %u [%d]", ((unsigned int) ((REC->dev) >> 20)), ((unsigned int) ((REC->dev) & ((1U << 20) - 1))), REC->rwbs, __get_str(cmd), (unsigned long long)REC->sector, REC->nr_sector, REC->error

这里我们知道如下信息:

这个trace里面,结构体提供了从common_type到cmd的所有字段域 提供了这个struct的offset,也就是具体位置 提供了打印格式

2.3 id

这里提供了id,这个id代表这个trace的id,我们可以从format上看到,如下:

ID: 1350

这个id是只读的,所以我们只能读到这个id,用作filter过滤

# cat id 1350

2.4 filter

这个用作过滤,我们可以知道,如果直接enable,我们没办法进行过滤,所以可以在这里添加多个过滤条件,如下:

假设我们只想看idle进程的信息,则如下:

echo "common_pid==0" > filter

如果想要关闭filter,直接echo 0即可

echo 0 > filter

注意,这里的filter只能是struct的成员,如果不是,就会失效,所以提前需要cat format看一下struct哪些成员可以过滤

2.5 trigger

trigger是trace默认提供的触发类型,我们可以通过cat获取可以使用的trigger类型,如下:

# cat trigger # Available triggers: # traceon traceoff stacktrace enable_event disable_event

这里提供了6个trigger,我们如果想要echo trigger,这里需要指定的语法格式,如下:

echo 'command[:count] [if filter]' > trigger

这里可以看到,我们需要填入command: trigger类型,count

次数 if filter 过滤条件。

2.5.1 traceon

这里是检测过滤条件满足的时候,一定次数下直接打开此trace,如下示例

echo 'traceon:5 if common_pid==0' > trigger

这里意思是如果pid为idle下触发blk_update_request达到5次,则主动打开此trace event

2.5.2 traceoff

echo 'traceoff:5 if common_pid==0' > trigger

这里意思是如果pid为idle下触发blk_update_request达到5次,则主动关闭此trace event

2.5.3 stacktrace

这里是打印此函数的堆栈,可以示例如下:

echo "stacktrace:1 if common_pid==0" > trigger

这里是当pid是idle的时候,打印一次堆栈,这样日志如下:

<idle>-0 [000] .Ns. 3780.543922: <stack trace> => trace_event_buffer_commit => trace_event_raw_event_block_rq_complete => blk_update_request => mmc_blk_cqe_complete_rq => mmc_blk_mq_complete => blk_done_softirq => __do_softirq => irq_exit => __handle_domain_irq => gic_handle_irq => el1_irq => cpuidle_enter_state => cpuidle_enter => call_cpuidle => do_idle => cpu_startup_entry => rest_init => arch_call_rest_init => start_kernel

2.5.4 enable_event

这是打开对于的event的trigger,如下:

echo "enable_event:block:block_rq_complete:2" > trigger

当block_rq_complete被触发两次时,打开event

2.5.5 disable_event

对于我们有关闭event的trigger,如下:

echo 'disable_event:block:block_rq_complete:2' > trigger

当block_rq_complete被触发两次时,关闭event

至此,我们简单了解了trace event的使用。