我们都知道ebpf为什么提供了一个内核态到用户态的一个数据交互中心, 这个数据交互中心就是bpf map, 在之前的一篇文章中我向你介绍了如何使用bpf map中的 array 改进 debug fs带来的一些问题。
这一篇, 我们主要想向你介绍如何在用户态遍历我们的bpf map的hash map。首先我们分析一下我们的hash map的使用场景。
在很多性能分析的场景中,当我们需要去统计一个线程需要执行多少次,比如我们需要统计有多少个 sh 进程正在执行的。我们就可以使用 bpf map 中的 hash map。我们可以把进程的名称设置为对应的键, 然后初始值设置为0, 对应的线程每执行一次,我们就让对应的值加上1。
probe sys_enter_execve{
map[comm()] |> count();
out("name: %-16s %6d", comm(), map[comm()]);
}
输出的结果如下:
name: node 0
name: sh 0
name: node 1
name: sh 1
name: node 2
name: sh 2
name: cpuUsage.sh 0
name: cpuUsage.sh 1
name: cpuUsage.sh 2
name: cpuUsage.sh 3
name: cpuUsage.sh 4
name: barad_agent 0
name: sh 3
name: sh 4
name: sh 5
观察上面的输出结果, 我们通用可以发现一个问题, 那就是, 这是结果是实时的, 也就是说执行一次就输出一次当前线程对应的map值, 也就是当前线程执行的次数。但是这样其实是不适合我们观察数据的。
那么怎样才能将我们的数据格式变得非常清晰呢, 一种非常好的方式就是就是在跟踪结束的时候遍历map按照顺序输出每一个键值对。我们可以看一下bpftrace的做法:
bpftrace -e 'tracepoint:raw_syscalls:sys_enter {
@[comm] = count(); }'
然后是输出结果
@[dockerd]: 7
@[code-b58957e67e]: 10
@[ntpd]: 12
@[sudo]: 18
@[cpptools-srv]: 22
@[cpptools]: 34
@[sleep]: 43
@[multipathd]: 47
@[tat_agent]: 49
@[bpftrace]: 63
@[dirname]: 63
@[chmod]: 64
@[which