• bpftrace:简便输出调试信息


    bpftrace是一种用于Linux增强型伯克利包过滤器(eBPF)的高级跟踪语言,使用LLVM作为后端将脚本编译为BPF字节码,并利用BCC与Linux BPF系统进行交互,以及现有的Linux跟踪功能:内核动态跟踪(kprobes)、用户级动态跟踪(uprobes)、和跟踪点(tracepoint)。bpftrace语言的灵感来自awkh、C、DTrace和SystemTap等前身跟踪器。
    上一篇<>实现了tracepoint定义及函数调用,本篇也以这个示例和官方提供示例为基础讲述。

    目录


    1. 基本用法
    1.1 自实现tracepoint输出
    1.2 简单示例
    2. 指令分析
    2.1 查询所有函数
    2.2 其它指令
    2.3 输出参数


    内容


    1. 基本用法

    bpftrace项目在github的地址

    1.1 自实现tracepoint输出

      上一篇<>中,定义test_trace函数,现在我们编写bpftrace语句:

    bpftrace -e 'tracepoint:test_trace:test_trace { printf("%s, %d\n", comm, args->pid) }'
    
    • 1

      语句执行后,执行write函数(触发trace_*函数):

    echo 123456 > /dev/test
    
    • 1

    在这里插入图片描述
      参考上图,使用bpftrace确实比较省事。


    1.2 简单示例

      进程打开的文件,输出当前调用

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

      系统调用计数(按程序)

    bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'
    
    • 1

      按进程读取字节

    bpftrace -e 'tracepoint:syscalls:sys_exit_read /args->ret/ { @[comm] = sum(args->ret); }'
    
    • 1

      按进程读取大小分布

    bpftrace -e 'tracepoint:syscalls:sys_exit_read { @[comm] = hist(args->ret); }'
    
    • 1

      显示每秒系统调用率

    bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @ = count(); } interval:s:1 { print(@); clear(@); }'
    
    • 1

      按进程跟踪磁盘大小

    bpftrace -e 'tracepoint:block:block_rq_issue { printf("%d %s %d\n", pid, comm, args->bytes); }'
    
    • 1

      按进程计算页面错误

    bpftrace -e 'software:faults:1 { @[comm] = count(); }'
    
    • 1

      按进程名称和 PID 计算 LLC 缓存未命中数(使用 PMC)

    bpftrace -e 'hardware:cache-misses:1000000 { @[comm, pid] = count(); }'
    
    • 1

      以 99 赫兹(hz)为 PID 189 配置用户级堆栈

    bpftrace -e 'profile:hz:99 /pid == 189/ { @[ustack] = count(); }'
    
    • 1

      为根 cgroup-v2 中的进程打开的文件

    bpftrace -e 'tracepoint:syscalls:sys_enter_openat /cgroup == cgroupid("/sys/fs/cgroup/unified/mycg")/ { printf("%s\n", str(args->filename)); }'
    
    • 1

    2. 指令分析

    2.1 查询所有函数

      查询函数指令:

    bpftrace  -l
    
    • 1

      每条数据有三部分组成,跟踪功能:类型(文件):函数名称

    tracepoint:syscalls:sys_enter_open
    tracepoint:syscalls:sys_exit_open
    tracepoint:syscalls:sys_enter_openat
    tracepoint:syscalls:sys_exit_openat
    tracepoint:syscalls:sys_enter_creat
    tracepoint:syscalls:sys_exit_creat
    tracepoint:test_trace:test_trace
    ... 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

      清楚需要调用的函数名称时(如test_trace),直接使用bpftrace -l | grep test_trace。


    2.2 其它指令

      -B MODE 输出缓冲模式(‘line’、‘full’ 或 ‘none’)

      -d 调试信息运行

      -dd 详细调试信息运行

      -e ‘program’ 执行这个程序

      -h 显示此帮助信息

      -l [search] 列出探测

      -p PID 在PID上启用USDT探测

      -c ‘CMD’ 运行CMD并在结果进程上启用USDT探测

      -v 详细消息

      --version bpftrace版本


    2.3 输出参数

      使用bpftrace -d(或-dd) -e 并在printf里指定输出一个结构函数,执行指令可以看到输出结构体定义,如:

    bpftrace -d -e 'tracepoint:test_trace:test_trace { printf("%s", str(args->filename)) }'
    
    ||
    \/
    
    #include 
    struct _tracepoint_test_trace_test_trace
    {
      unsigned short common_type;
      unsigned char common_flags;
      unsigned char common_preempt_count;
      int common_pid;
      char comm[16];
      pid_t pid;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

      这里指定了str(args->filename),输出字符串文件名称,执行指令可以看到结构体列表。(filename参数不正确,但也能打印出结构体列表,获得相关参数即可)

  • 相关阅读:
    面经综合总结
    一个简单的小项目 —— 我的博客系统
    RK3568笔记一:RKNN开发环境搭建
    Lua位或操作
    【Flask+gunicorn+ supervisor】部署python项目
    Elasticsearch(十五)搜索---搜索匹配功能⑥--基于地理位置查询
    latex中appendix附录怎么写
    项目管理实战总结(一)
    济南建筑模板生产厂家有哪些?
    03【Controller方法返回值详解】
  • 原文地址:https://blog.csdn.net/a29562268/article/details/126216522