bpftrace 使用笔记

bpftrace 使用笔记

bpftrace 是基于BPF和BCC的开源系统跟踪工具. bpftrace 自带了许多性能工具,同时还提供一个高级编程语言环境,用于创建自定义的工具.
一般Linux发行版都可直接通过安装包安装使用, 我自己的环境由于升级了KERNEL导致不能正常使用, 只能通过源码重新构建使用.

环境准备:

$ uname -a
Linux fc29 5.12.7-300.fc29.x86_64 #1 SMP Fri May 28 13:45:39 CST 2021 x86_64 x86_64 x86_64 GNU/Linux

KENREL配置需确保以下功能模块是开启状态:

CONFIG_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_HAVE_EBPF_JIT=y
CONFIG_BPF_EVENTS=y
CONFIG_FTRACE_SYSCALLS=y
CONFIG_FUNCTION_TRACER=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_DYNAMIC_FTRACE=y
CONFIG_HAVE_KPROBES=y
CONFIG_KPROBES=y
CONFIG_KPROBE_EVENTS=y
CONFIG_ARCH_SUPPORTS_UPROBES=y
CONFIG_UPROBES=y
CONFIG_UPROBE_EVENTS=y
CONFIG_DEBUG_FS=y

build

$ sudo dnf install -y bison flex cmake make git gcc-c++ elfutils-libelf-devel zlib-devel llvm-devel clang-devel bcc-devel systemtap-sdt-devel binutils-devel libbpf-devel gtest-devel gmock-devel
$ cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_TESTING:BOOL=OFF -DBUILD_SHARED_LIBS:BOOL=OFF .
$ make
$ make install
$ bpftrace--info
System
  OS: Linux 5.12.7-300.fc29.x86_64 #1 SMP Fri May 28 13:45:39 CST 2021
  Arch: x86_64

Build
  version: v0.12.1
  LLVM: 7.0.1
  foreach_sym: yes
  unsafe uprobe: no
  bfd: yes
  bpf_attach_kfunc: yes
  bcc_usdt_addsem: yes
  bcc bpf_attach_uprobe refcount: yes
  libbpf: yes
  libbpf btf dump: yes
  libbpf btf dump type decl: yes

Kernel helpers
  probe_read: yes
  probe_read_str: yes
  probe_read_user: yes
  probe_read_user_str: yes
  probe_read_kernel: yes
  probe_read_kernel_str: yes
  get_current_cgroup_id: yes
  send_signal: yes
  override_return: no
  get_boot_ns: yes
  dpath: yes

Kernel features
  Instruction limit: 1000000
  Loop support: yes
  btf (depends on Build:libbpf): yes
  map batch (depends on Build:libbpf): yes
  uprobe refcount (depends on Build:bcc bpf_attach_uprobe refcount): yes

Map types
  hash: yes
  percpu hash: yes
  array: yes
  percpu array: yes
  stack_trace: yes
  perf_event_array: yes

Probe types
  kprobe: yes
  tracepoint: yes
  perf_event: yes
  kfunc: yes
  iter:task: yes
  iter:task_file: yes

基本语法:

{...}: Action 执行代码块
/.../: Filtering 过滤条件
//, /*: 注释

Probes

AliasTypeDescription
ttracepoint内核静态探针
Uusdt用户态静态定义探针
kkprobe内核态动态函数探针
krkretprobe内核态动态函数返回值探针
fkfunc基于BPF的内核态动态函数探针
frkretfunc基于BPF的内核态动态函数返回值探针
uuprobe用户态函数探针
ururetprobe用户态函数返回值探针
ssoftware内核软件事件
hhardware基于硬件计数器的探针
wwatchpoint基于内存的监测点事件
pprofile对所有CPU进行时间采样
iinterval周期性报告(从一个CPU)
iter遍历跟踪内核对象
BEGINbpftrace 启动执行动作
ENDbpftrace 退出执行动作

列出bpftrace支持的探针

$ bpftrace -l
$ bpftrace -l "k:*net*"
$ bpftrace -l "k:tcp*"
$ bpftrace -l "kprobe:*net*"
$ bpftrace -l "f:tcp*"
$ bpftrace -l "kfunc:tcp*"
$ bpftrace -l "t:*"
$ bpftrace -l "tracepoint:*"
$ bpftrace -l "tracepoint:net:*"
$ bpftrace -l "tracepoint:syscalls:*"
$ bpftrace -l "tracepoint:syscalls:sys_enter_*"
$ bpftrace -l 'tracepoint:sock:*'
tracepoint:sock:inet_sock_set_state
tracepoint:sock:sock_exceed_buf_limit
tracepoint:sock:sock_rcvqueue_full

列出 tracepoint 函数调用参数

$ bpftrace  -lv tracepoint:net:netif_receive_skb
tracepoint:net:netif_receive_skb
    void * skbaddr
    unsigned int len
    __data_loc char[] name

$ bpftrace  -lv tracepoint:net:net_dev_xmit
tracepoint:net:net_dev_xmit
    void * skbaddr
    unsigned int len
    int rc
    __data_loc char[] name

列出内核 struct 结构体数据:

$ bpftrace -lv "struct path"
struct path {
	struct vfsmount *mnt;
	struct dentry *dentry;
};
$ bpftrace  -lv "struct sock"
$ bpftrace  -lv "struct sock_common"

列出 kprobe/kfunc 函数调用参数

通过内核 vmlinux 检查 kprobe 函数调用参数, 
# gdb -q  ~/rpmbuild/BUILD/kernel-5.12.7/linux-5.12.7-300.fc29.x86_64/vmlinux --ex 'p tcp_set_state'
Reading symbols from /root/rpmbuild/BUILD/kernel-5.12.7/linux-5.12.7-300.fc29.x86_64/vmlinux...done.
$1 = {void (struct sock *, int)} 0xffffffff81a40730 <tcp_set_state>
(gdb) q

# grep tcp_set_state /usr/src/kernels/5.12.7-300.fc29.x86_64/include/* -r
/usr/src/kernels/5.12.7-300.fc29.x86_64/include/net/tcp.h:void tcp_set_state(struct sock *sk, int state);

$ bpftrace  -lv "kfunc:tcp_set_state"
kfunc:tcp_set_state
    struct sock * sk
    int state
    
$ bpftrace  -e 'kprobe:tcp_set_state { printf("%p %d\n", arg0, arg1); }'

内核动态探针 kprobe/kretprobe/kfunc/kretfunc

可对内核函数开始或结束位置进行动态跟踪(插桩).

示例1:

$ cat ./vfs_open.bt 
#!/usr/bin/env bpftrace
#include <linux/path.h>
#include <linux/dcache.h>

kprobe:vfs_open
{
	printf("open path: %s\n", str(((struct path *)arg0)->dentry->d_name.name));
}

跟踪 kprobe:vfs_open()函数,将vfs_open 第一个参数打开的目录路径arg0转换为(struct path *)并输出.

$ bpftrace -lv 'f:vfs_open'
kfunc:vfs_open
    const struct path * path
    struct file * file
    int retval

$ sudo ./vfs_open.bt 
Attaching 1 probe...
open path: cat
open path: ld-2.28.so
open path: ld.so.cache
open path: libc-2.28.so
open path: locale-archive
open path: tcpstates.bt
open path: ls
open path: ld-2.28.so
open path: ld.so.cache
open path: libselinux.so.1
open path: libcap.so.2.25
open path: libc-2.28.so
open path: libpcre2-8.so.0.8.0
open path: libdl-2.28.so
open path: libpthread-2.28.so
open path: locale-archive
open path: tools
open path: interrupts
open path: stat
^C

示例2:
统计 vfs_read 每次执行耗时分布:

$ bpftrace -e 'kprobe:vfs_read { @start[tid] = nsecs; } kretprobe:vfs_read /@start[tid]/ { @ns[comm] = hist(nsecs - @start[tid]); delete(@start[tid]); }'
Attaching 2 probes...
^C

@ns[NetworkManager]: 
[2K, 4K)               1 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|

@ns[pmdaxfs]: 
[512, 1K)              3 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1K, 2K)               1 |@@@@@@@@@@@@@@@@@                                   |
[2K, 4K)               2 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                  |
[4K, 8K)               0 |                                                    |
[8K, 16K)              0 |                                                    |
[16K, 32K)             0 |                                                    |
[32K, 64K)             0 |                                                    |
[64K, 128K)            1 |@@@@@@@@@@@@@@@@@                                   |

@ns[pmcd]: 
[512, 1K)              1 |@@@@@@@@@@                                          |
[1K, 2K)               5 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2K, 4K)               1 |@@@@@@@@@@                                          |
[4K, 8K)               0 |                                                    |
[8K, 16K)              0 |                                                    |
[16K, 32K)             1 |@@@@@@@@@@                                          |

@ns[cat]: 
[512, 1K)              6 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1K, 2K)               2 |@@@@@@@@@@@@@@@@@                                   |
[2K, 4K)               2 |@@@@@@@@@@@@@@@@@                                   |
[4K, 8K)               1 |@@@@@@@@                                            |
[8K, 16K)              0 |                                                    |
[16K, 32K)             0 |                                                    |
[32K, 64K)             0 |                                                    |
[64K, 128K)            0 |                                                    |
[128K, 256K)           0 |                                                    |
[256K, 512K)           1 |@@@@@@@@                                            |

@ns[in:imjournal]: 
[512, 1K)              2 |@@@                                                 |
[1K, 2K)              31 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2K, 4K)               1 |@                                                   |

@ns[pmdakvm]: 
[1K, 2K)              40 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[2K, 4K)               2 |@@                                                  |

@ns[bash]: 
[512, 1K)              8 |@@@@@@@@@@                                          |
[1K, 2K)               5 |@@@@@@                                              |
[2K, 4K)              39 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4K, 8K)               1 |@                                                   |
[8K, 16K)              2 |@@                                                  |
[16K, 32K)             6 |@@@@@@@@                                            |
[32K, 64K)             0 |                                                    |
[64K, 128K)            0 |                                                    |
[128K, 256K)           1 |@                                                   |
[256K, 512K)           1 |@                                                   |
[512K, 1M)             1 |@                                                   |

@ns[ls]: 
[512, 1K)             58 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[1K, 2K)              31 |@@@@@@@@@@@@@@@@@@@@@@@@@@@                         |
[2K, 4K)               7 |@@@@@@                                              |

@ns[sshd]: 
[1K, 2K)              46 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@                        |
[2K, 4K)              84 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4K, 8K)               4 |@@                                                  |
[8K, 16K)             11 |@@@@@@                                              |
[16K, 32K)             2 |@                                                   |

@ns[pmdalinux]: 
[256, 512)            25 |@@@@@@@@@@@@@@@@@                                   |
[512, 1K)             58 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@           |
[1K, 2K)              23 |@@@@@@@@@@@@@@@@                                    |
[2K, 4K)              17 |@@@@@@@@@@@@                                        |
[4K, 8K)              21 |@@@@@@@@@@@@@@                                      |
[8K, 16K)             73 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16K, 32K)             4 |@@                                                  |
[32K, 64K)             9 |@@@@@@                                              |
[64K, 128K)            4 |@@                                                  |
[128K, 256K)           1 |                                                    |

@ns[irqbalance]: 
[256, 512)             7 |@@@                                                 |
[512, 1K)              9 |@@@@                                                |
[1K, 2K)              52 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@                        |
[2K, 4K)               4 |@@                                                  |
[4K, 8K)              78 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@         |
[8K, 16K)             94 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16K, 32K)             6 |@@@                                                 |
[32K, 64K)             5 |@@                                                  |
[64K, 128K)            5 |@@                                                  |

@ns[pmdaproc]: 
[512, 1K)              3 |                                                    |
[1K, 2K)               0 |                                                    |
[2K, 4K)             389 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4K, 8K)              42 |@@@@@                                               |
[8K, 16K)              3 |                                                    |

@start[1905]: 1922797996393161
@start[1907]: 1922797996743168
@start[1904]: 1922798001240070
@start[1906]: 1922798017500978
@start[5624]: 1922821038865193
@start[19276]: 1922821050726967

内核静态探针 Tracepoints

示例:

1. Listing probes
bpftrace -l 'tracepoint:syscalls:sys_enter_*'

2. Hello world
bpftrace -e 'BEGIN { printf("hello world\n"); }'

3. File opens
bpftrace -e 'tracepoint:syscalls:sys_enter_open { printf("%s %s\n", comm, str(args->filename)); }'

4. Syscall counts by process
bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'

5. Distribution of read() bytes
bpftrace -e 'tracepoint:syscalls:sys_exit_read /pid == 18644/ { @bytes = hist(args->retval); }'

6. Kernel dynamic tracing of read() bytes
bpftrace -e 'kretprobe:vfs_read { @bytes = lhist(retval, 0, 2000, 200); }'

7. Timing read()s
bpftrace -e 'kprobe:vfs_read { @start[tid] = nsecs; }
    kretprobe:vfs_read /@start[tid]/ { @ns[comm] = hist(nsecs - @start[tid]); delete(@start[tid]); }'

8. Count process-level events
bpftrace -e 'tracepoint:sched:sched* { @[name] = count(); } interval:s:5 { exit(); }'

9. Profile on-CPU kernel stacks
bpftrace -e 'profile:hz:99 { @[stack] = count(); }'

10. Scheduler tracing
bpftrace -e 'tracepoint:sched:sched_switch { @[stack] = count(); }'

11. Block I/O tracing
bpftrace -e 'tracepoint:block:block_rq_complete { @ = hist(args->nr_sector * 512); }'

inet_sock_set_state

tracepoint:sock:inet_sock_set_state:

$ bpftrace -lv t:sock:inet_sock_set_state
tracepoint:sock:inet_sock_set_state
    const void * skaddr
    int oldstate
    int newstate
    __u16 sport
    __u16 dport
    __u16 family
    __u16 protocol
    __u8 saddr[4]
    __u8 daddr[4]
    __u8 saddr_v6[16]
    __u8 daddr_v6[16]
    
$ bpftrace  -e 'tracepoint:sock:inet_sock_set_state { printf("%d %d\n", args->oldstate, args->newstate); }'
Attaching 1 probe...
7 2
2 1
10 3
3 1
7 2
2 1
1 4
4 11
11 7
1 4
1 8
8 9
4 5
5 7
9 7

$ bpftrace  -e 'tracepoint:sock:inet_sock_set_state { printf("%-15s %-15s %d %d\n", ntop(2, args->saddr), ntop(2, args->daddr), args->oldstate, args->newstate); }'

用户态函数探针 uprobe/uretprobe

uprobe/uretprobe 分别为用户态函数调用和函数返回探针:

uprobe: arg0, arg1, ..., argN
uretprobe: retval

以下示例演示跟踪用户态主函数main:

# cat /root/wrks/test.c 
#include <stdio.h>

int main(int argc, char **argv)
{
	printf("hello world!\n");
	return 0;
}

# gcc -g test.c -o test

通过用户态函数地址跟踪

# objdump -tT test |grep main
0000000000000000       F *UND*	0000000000000000              __libc_start_main@@GLIBC_2.2.5
0000000000401126 g     F .text	0000000000000020              main
0000000000000000      DF *UND*	0000000000000000  GLIBC_2.2.5 __libc_start_main
$ bpftrace -e 'uprobe:/root/wrks/test:0x401126 { printf("test\n");}'
Attaching 1 probe...
# /root/wrks/test 
hello world!
$ bpftrace -e 'uprobe:/root/wrks/test:0x401126 { printf("test\n");}'
Attaching 1 probe...
test
^C

通过用户态函数名称跟踪

# objdump  -d test
...
0000000000401126 <main>:
  401126:	55                   	push   %rbp
  401127:	48 89 e5             	mov    %rsp,%rbp
  40112a:	48 83 ec 10          	sub    $0x10,%rsp
  40112e:	89 7d fc             	mov    %edi,-0x4(%rbp)
  401131:	48 89 75 f0          	mov    %rsi,-0x10(%rbp)
  401135:	bf 10 20 40 00       	mov    $0x402010,%edi
  40113a:	e8 f1 fe ff ff       	callq  401030 <puts@plt>
  40113f:	b8 00 00 00 00       	mov    $0x0,%eax
  401144:	c9                   	leaveq 
  401145:	c3                   	retq   
  401146:	66 2e 0f 1f 84 00 00 	nopw   %cs:0x0(%rax,%rax,1)
  40114d:	00 00 00 
...
$ bpftrace -e 'uprobe:/root/wrks/test:main { printf("test\n");}'
Attaching 1 probe...
test

$ bpftrace -e 'uprobe:/root/wrks/test:main { printf("arg0: %d\n", arg0);}'
Attaching 1 probe...
arg0: 1

unsafe

基于硬件计数器的探针 hardware

当前系统支持的硬件计数器:

$ bpftrace  -lv 'h:*'
hardware:backend-stalls:
hardware:branch-instructions:
hardware:branch-misses:
hardware:bus-cycles:
hardware:cache-misses:
hardware:cache-references:
hardware:cpu-cycles:
hardware:frontend-stalls:
hardware:instructions:
hardware:ref-cycles:

示例 - 统计30秒内cache-missed次数超过1000000的进程

bpftrace -e 'hardware:cache-misses:1000000 { @[pid] = count(); } interval:s:30 { exit(); }'

其他示例

kstack

分析内核实时函数栈, 统计ip_output 调用栈:

$ bpftrace -e 'kprobe:ip_output { @[kstack()] = count(); } interval:s:10 { exit(); }'
Attaching 2 probes...

...
@[
    ip_output+1
    __ip_queue_xmit+349
    __tcp_transmit_skb+2718
    tcp_write_xmit+971
    tcp_tsq_handler+57
    tcp_tasklet_func+205
    tasklet_action_common.isra.18+102
    __do_softirq+223
    irq_exit_rcu+218
    common_interrupt+127
    asm_common_interrupt+30
    cpuidle_enter_state+219
    cpuidle_enter+41
    do_idle+573
    cpu_startup_entry+25
    start_secondary+273
    secondary_startup_64_no_verify+194
]: 8
@[
    ip_output+1
    __ip_queue_xmit+349
    __tcp_transmit_skb+2718
    tcp_write_xmit+971
    __tcp_push_pending_frames+50
    tcp_sendmsg_locked+3206
    tcp_sendmsg+39
    sock_sendmsg+84
    sock_write_iter+140
    new_sync_write+376
    vfs_write+445
    ksys_write+157
    do_syscall_64+51
    entry_SYSCALL_64_after_hwframe+68
]: 45
...
#  bpftrace -e 'kprobe:ip_output { @[kstack(3)] = count(); }'
Attaching 1 probe...
^C

@[
    ip_output+1
    __ip_queue_xmit+349
    __tcp_transmit_skb+2718
]: 54

tcp_sendmsg

$ bpftrace -e 'k:tcp_sendmsg { @size = hist(arg2); } interval:s:10 { exit(); }'
Attaching 2 probes...


@size: 
[32, 64)               6 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                     |
[64, 128)              2 |@@@@@@@@@@                                          |
[128, 256)             5 |@@@@@@@@@@@@@@@@@@@@@@@@@@                          |
[256, 512)            10 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[512, 1K)              1 |@@@@@                                               |


#bpftrace -e 'kr:tcp_sendmsg { @retvals[retval > 0 ? 0 : retval] = count(); } interval:s:30 { exit(); }'
Attaching 2 probes...


@retvals[0]: 148

#!/usr/local/bin/bpftrace

#include <net/sock.h>

k:tcp_sendmsg
{
    @sk[tid] = arg0;
    @size[tid] = arg2;
}

kr:tcp_sendmsg
/@sk[tid]/
{
    $sk = (struct sock *)@sk[tid];
    $size = @size[tid];
    $af = $sk->__sk_common.skc_family;
    if ($af == AF_INET) {
	    $daddr = ntop($af, $sk->__sk_common.skc_daddr);
	    $saddr = ntop($af, $sk->__sk_common.skc_rcv_saddr);
	    $lport = $sk->__sk_common.skc_num;
	    $dport = $sk->__sk_common.skc_dport;
	    $dport = ($dport >> 8) | (($dport << 8) & 0xff00);
	    printf("%-15s %-5d -> %-15s %-5d: %d bytes, retval %d\n",
	        $saddr, $lport, $daddr, $dport, $size, retval);
    } else {
	    printf("IPv6...\n");
    }
    delete(@sk[tid]);
    delete(@size[tid]);
}
# ./tcp_sendmsg.bt 
    Attaching 2 probes...
    10.0.0.65       49978 -> 52.37.243.173   443  : 63 bytes, retval 63
    127.0.0.1       58566 -> 127.0.0.1       22   : 36 bytes, retval 36
    127.0.0.1       22    -> 127.0.0.1       58566: 36 bytes, retval 36
    [...]
监控tcp_sendmsg发送大于8192字节进程pid
bpftrace -e 'k:tcp_sendmsg /arg2 > 8192/ { printf("PID %d: %d bytes\n", pid, arg2); }'

统计调用tcp_sendmsg进程发送字节分布
bpftrace -e 'k:tcp_sendmsg { @size[pid, comm] = hist(arg2); }'
Attaching 1 probe...
^C

@size[2326, sshd]: 
[32, 64)              22 |@@@@@@@@@@@@@@@@@@@                                 |
[64, 128)             19 |@@@@@@@@@@@@@@@@                                    |
[128, 256)            59 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[256, 512)            33 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                       |

统计tcp_sendmsg 返回值分布
bpftrace -e 'kr:tcp_sendmsg { @return[retval] = count(); }'

每秒统计tcp_sendmsg 调用次数&发送总计&平均字节
bpftrace -e 'k:tcp_sendmsg { @size = stats(arg2); }  interval:s:1 { print(@size); clear(@size); }'

统计 tcp_sendmsg 调用栈分布
bpftrace -e 'k:tcp_sendmsg { @[kstack] = count(); }'

限制调用栈层次为3层, 统计 tcp_sendmsg 调用栈分布
bpftrace -e 'k:tcp_sendmsg { @[kstack(3)] = count(); }'

bpftrace -e 'k:tcp_sendmsg { @ts[tid] = nsecs; }
        kr:tcp_sendmsg /@ts[tid]/ { @ns = hist(nsecs - @ts[tid]); delete(@ts[tid]); }'
Attaching 2 probes...
^C

@ns: 
[512, 1K)             21 |@                                                   |
[1K, 2K)              14 |@                                                   |
[2K, 4K)             291 |@@@@@@@@@@@@@@@@@@@@@@@@@@                          |
[4K, 8K)             574 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[8K, 16K)             33 |@@                                                  |
[16K, 32K)             5 |                                                    |

@ts[1614]: 1826887636941576

hrtimer_start

统计每个hrtimer_start函数的参数调用频率

$ bpftrace -lv 't:timer:hrtimer_start'
tracepoint:timer:hrtimer_start
    void * hrtimer
    void * function
    s64 expires
    s64 softexpires
    enum hrtimer_mode mode
$ bpftrace -e 't:timer:hrtimer_start { @[ksym(args->function)] = count(); }'
Attaching 1 probe...
^C

@[timerfd_tmrproc]: 5
@[posix_timer_fn]: 8
@[it_real_fn]: 13
@[watchdog_timer_fn]: 256
@[hrtimer_wakeup]: 431
@[tick_sched_timer]: 22141

Reference

Kernel analysis with bpftrace
bpftrace Reference Guide
bpftrace Install Guide
bpftrace Cheat Sheet
BPF Performance Tools (book)
Linux Extended BPF (eBPF) Tracing Tools
tutorial_one_liners_chinese
Tracing a packet journey using Linux tracepoints, perf and eBPF
https://github.com/yadutaf/tracepkt

  • 4
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值