iovisor/bcc项目Python开发教程:从入门到实战

iovisor/bcc项目Python开发教程:从入门到实战

bcc iovisor/bcc: 是基于 Linux eBPF 的新型网络分析工具,可用于 Linux 系统的性能监控、网络追踪和安全分析等领域。适合对 bcc 项目地址: https://gitcode.com/gh_mirrors/bc/bcc

本文将通过一系列实战案例,带您深入了解如何使用Python开发基于iovisor/bcc项目的eBPF工具。我们将从基础概念开始,逐步深入到实际应用开发。

一、eBPF与BCC基础

eBPF(扩展伯克利包过滤器)是Linux内核中的一项革命性技术,它允许用户在不修改内核源代码的情况下运行沙盒程序。BCC(BPF Compiler Collection)则是构建在eBPF之上的工具集,提供了Python、C++等高级语言接口。

1.1 Hello World示例

让我们从一个最简单的"Hello World"程序开始:

from bcc import BPF
BPF(text='int kprobe__sys_clone(void *ctx) { bpf_trace_printk("Hello, World!\\n"); return 0; }').trace_print()

这个程序有六个关键点需要理解:

  1. text='...':定义内联的BPF程序,使用C语言编写
  2. kprobe__sys_clone:内核动态跟踪的快捷方式,自动探测sys_clone系统调用
  3. void *ctx:上下文参数,这里我们不需要使用它
  4. bpf_trace_printk():内核中的简单打印函数,输出到trace_pipe
  5. return 0:必需的返回值
  6. .trace_print():读取trace_pipe并打印输出

1.2 进阶Hello示例

让我们看一个更完整的版本:

from bcc import BPF
from bcc.utils import printb

prog = """
int hello(void *ctx) {
    bpf_trace_printk("Hello, World!\\n");
    return 0;
}
"""

b = BPF(text=prog)
b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="hello")

print("%-18s %-16s %-6s %s" % ("TIME(s)", "COMM", "PID", "MESSAGE"))

while 1:
    try:
        (task, pid, cpu, flags, ts, msg) = b.trace_fields()
    except ValueError:
        continue
    except KeyboardInterrupt:
        exit()
    printb(b"%-18.9f %-16s %-6d %s" % (ts, task, pid, msg))

这个版本展示了:

  • 分离BPF程序定义与加载
  • 显式附加kprobe
  • 更完善的输出格式化

二、内核事件跟踪实战

2.1 同步调用跟踪

下面是一个跟踪sync系统调用的示例,可以检测短时间内多次调用sync的情况:

from bcc import BPF

b = BPF(text="""
#include <uapi/linux/ptrace.h>

BPF_HASH(last);

int do_trace(struct pt_regs *ctx) {
    u64 ts, *tsp, delta, key = 0;
    
    tsp = last.lookup(&key);
    if (tsp != NULL) {
        delta = bpf_ktime_get_ns() - *tsp;
        if (delta < 1000000000) {
            bpf_trace_printk("%d\\n", delta / 1000000);
        }
        last.delete(&key);
    }

    ts = bpf_ktime_get_ns();
    last.update(&key, &ts);
    return 0;
}
""")

b.attach_kprobe(event=b.get_syscall_fnname("sync"), fn_name="do_trace")
print("Tracing for quick sync's... Ctrl-C to end")
[...]

关键点:

  • BPF_HASH(last):创建哈希表类型的BPF映射
  • bpf_ktime_get_ns():获取当前纳秒级时间戳
  • 映射操作:lookup/delete/update

2.2 磁盘I/O分析

下面是一个分析磁盘I/O大小的直方图工具:

from bcc import BPF

b = BPF(text="""
#include <uapi/linux/ptrace.h>
#include <linux/blkdev.h>

BPF_HISTOGRAM(dist);

int kprobe__blk_account_io_done(struct pt_regs *ctx, struct request *req) {
    dist.increment(bpf_log2l(req->__data_len / 1024));
    return 0;
}
""")
[...]
b["dist"].print_log2_hist("kbytes")

这个工具展示了:

  • BPF_HISTOGRAM:创建直方图类型的BPF映射
  • bpf_log2l():计算对数用于直方图分桶
  • print_log2_hist():打印对数直方图

三、性能优化技巧

3.1 使用PERF_OUTPUT替代trace_printk

bpf_trace_printk适合调试但不适合生产环境,更好的方式是使用BPF_PERF_OUTPUT

from bcc import BPF

prog = """
#include <linux/sched.h>

struct data_t {
    u32 pid;
    u64 ts;
    char comm[TASK_COMM_LEN];
};
BPF_PERF_OUTPUT(events);

int hello(struct pt_regs *ctx) {
    struct data_t data = {};
    data.pid = bpf_get_current_pid_tgid();
    data.ts = bpf_ktime_get_ns();
    bpf_get_current_comm(&data.comm, sizeof(data.comm));
    events.perf_submit(ctx, &data, sizeof(data));
    return 0;
}
"""

b = BPF(text=prog)
[...]
b["events"].open_perf_buffer(print_event)
while 1:
    b.perf_buffer_poll()

优势包括:

  • 更高的性能
  • 更灵活的数据结构
  • 避免全局trace_pipe的冲突

3.2 内核版本兼容性处理

由于不同内核版本函数可能变化,需要做兼容处理:

if BPF.get_kprobe_functions(b'__blk_account_io_done'):
    b.attach_kprobe(event="__blk_account_io_done", fn_name="trace_req_done")
elif BPF.get_kprobe_functions(b'blk_account_io_done'):
    b.attach_kprobe(event="blk_account_io_done", fn_name="trace_req_done")
else:
    b.attach_kprobe(event="blk_mq_end_request", fn_name="trace_req_done")

四、总结与最佳实践

通过本教程,我们学习了:

  1. 基本BPF程序结构与加载方式
  2. 内核函数跟踪与系统调用跟踪
  3. BPF映射的使用:哈希表、直方图等
  4. 性能数据采集与输出优化
  5. 内核版本兼容性处理

开发BCC工具时的最佳实践:

  1. 优先使用BPF_PERF_OUTPUT而非bpf_trace_printk
  2. 合理选择映射类型:哈希表适合键值对,直方图适合分布统计
  3. 注意内核版本差异,做好兼容处理
  4. 复杂数据结构可先在C中定义,再通过Python访问
  5. 充分利用BCC提供的各种辅助函数简化开发

希望本教程能帮助您快速掌握BCC Python开发的核心要点,为开发更复杂的内核观测工具打下坚实基础。

bcc iovisor/bcc: 是基于 Linux eBPF 的新型网络分析工具,可用于 Linux 系统的性能监控、网络追踪和安全分析等领域。适合对 bcc 项目地址: https://gitcode.com/gh_mirrors/bc/bcc

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡霆圣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值