找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3221

积分

0

好友

417

主题
发表于 2025-12-24 04:38:49 | 查看: 62| 回复: 0

在Linux系统中,perf是一个强大的性能分析工具,它允许开发者深入测量和分析内核及用户空间程序的运行状况,并获取调用堆栈信息。通过利用硬件计数器和软件事件,perf能够高效收集性能数据。更多关于Linux系统运维和性能调优的知识,可以在云栈社区的运维/DevOps板块找到

eBPF程序通过与Linux的perf子系统结合,能以极低的开销对系统、内核或应用程序进行采样分析。这为实时性能监控和问题诊断提供了强大支持。eBPF技术在现代云原生架构中应用广泛,相关实践可参考云栈社区的云原生/IaaS板块

以下是一个基于libbpf-bootstrap示例的eBPF程序代码,展示了如何实现profile功能:

SEC("perf_event")
int profile(void *ctx)
{
    int pid = bpf_get_current_pid_tgid() >> 32;
    int cpu_id = bpf_get_smp_processor_id();
    struct stacktrace_event *event;
    int cp;

    event = bpf_ringbuf_reserve(&events, sizeof(*event), 0);
    if (!event)
        return 1;

    event->pid = pid;
    event->cpu_id = cpu_id;
    if (bpf_get_current_comm(event->comm, sizeof(event->comm)))
        event->comm[0] = 0;

    event->kstack_sz = bpf_get_stack(ctx, event->kstack, sizeof(event->kstack), 0);
    event->ustack_sz = bpf_get_stack(ctx, event->ustack, sizeof(event->ustack), BPF_F_USER_STACK);

    bpf_ringbuf_submit(event, 0);
    return 0;
}

SEC("perf_event")是libbpf加载器的一个“标签”或“指令”,它标识这是一个BPF_PROG_TYPE_PERF_EVENT类型的程序,并将作为回调函数挂载到Linux内核的Perf Event子系统上。需要注意的是,SEC("perf_event")本身并不指定具体监控的事件类型(如CPU周期或缓存未命中),事件配置由用户态代码完成。

在以上代码中,bpf_get_stack函数用于将当前的调用栈直接拷贝到event->kstack数组中,支持内核栈和用户栈的捕获。

用户态代码负责配置和挂载事件。以下是一个关键的用户态代码片段:

memset(&attr, 0, sizeof(attr));
// 如果有 -s 参数,使用软件事件 (PERF_TYPE_SOFTWARE)
// 否则默认使用硬件事件 (PERF_TYPE_HARDWARE)
attr.type = sw_event ? PERF_TYPE_SOFTWARE : PERF_TYPE_HARDWARE;
// 具体的事件配置:
// 软件事件 -> CPU_CLOCK (基于时间的采样,不依赖硬件计数器)
// 硬件事件 -> CPU_CYCLES (基于 CPU 周期的采样,更精确但虚拟化环境可能不支持)
attr.config = sw_event ? PERF_COUNT_SW_CPU_CLOCK : PERF_COUNT_HW_CPU_CYCLES;
attr.sample_freq = freq;  // 设置采样频率,比如 99Hz
attr.freq = 1;           // 告诉内核 attr.sample_freq 是频率而不是周期

挂载过程针对每个在线CPU进行,以确保全系统监控:

for (cpu = 0; cpu < num_cpus; cpu++) {
    // 1. 跳过离线 CPU
    if (cpu >= num_online_cpus || !online_mask[cpu])
        continue;

    /* Set up performance monitoring on a CPU/Core */
    // 2. 关键系统调用:perf_event_open
    // pid = -1: 监控该 CPU 上运行的所有进程
    // cpu = cpu: 指定监控第几个 CPU 核
    pefd = perf_event_open(&attr, pid, cpu, -1, PERF_FLAG_FD_CLOEXEC);

    // ... 错误处理 ...

    /* Attach a BPF program on a CPU */
    // 3. 将 BPF 程序挂载到这个 perf event 文件描述符 (pefd) 上
    links[cpu] = bpf_program__attach_perf_event(skel->progs.profile, pefd);
}

这种设计使得perf_event类型的eBPF程序能够实现对系统中所有在线CPU的全面监控,为性能分析和优化提供精细数据。




上一篇:Pyftpdlib异步FTP服务器库详解:Python构建高性能文件传输服务
下一篇:AI对法律行业的冲击:从成本重构到职业重塑的分析
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-8 12:23 , Processed in 0.381530 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表