0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

教你们如何使用eBPF追踪LINUX内核

Linux阅码场 来源:Linux内核之旅 作者:梁金荣 2021-04-20 11:26 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

1. 前言

我们可以使用BPF对Linux内核进行跟踪,收集我们想要的内核数据,从而对Linux中的程序进行分析和调试。与其它的跟踪技术相比,使用BPF的主要优点是几乎可以访问Linux内核和应用程序的任何信息,同时,BPF对系统性能影响很小,执行效率很高,而且开发人员不需要因为收集数据而修改程序。

本文将介绍保证BPF程序安全的BPF验证器,然后以BPF程序的工具集BCC为例,分享kprobes和tracepoints类型的BPF程序的使用及程序编写示例。

2. BPF验证器

BPF借助跟踪探针收集信息并进行调试和分析,与其它依赖于重新编译内核的工具相比,BPF程序的安全性更高。重新编译内核引入外部模块的方式,可能会因为程序的错误而产生系统奔溃。BPF程序的验证器会在BPF程序加载到内核之前分析程序,消除这种风险。

BPF验证器执行的第一项检查是对BPF虚拟机加载的代码进行静态分析,目的是确保程序能够按照预期结束。验证器在进行第一项检查时所做工作为:

程序不包含控制循环;

程序不会执行超过内核允许的最大指令数;

程序不包含任何无法到达的指令;

程序不会超出程序界限。

BPF验证器执行的第二项检查是对BPF程序进行预运行,所做工作为:

分析BPF程序执行的每条指令,确保不会执行无效指令;

检查所有内存指针是否可以正确访问和引用;

预运行将程序控制流的执行结果通知验证器,确保BPF程序最终都会执行BPF_EXIT指令。

3. 内核探针 kprobes

内核探针可以跟踪大多数内核函数,并且系统损耗最小。当跟踪的内核函数被调用时,附加到探针的BPF代码将被执行,之后内核将恢复正常模式。

3.1 kprobes类BPF程序的优缺点

优点 动态跟踪内核,可跟踪的内核函数众多,能够提取内核绝大部分信息。

缺点 没有稳定的应用程序二进制接口,可能随着内核版本的演进而更改。

3.2 kprobes

kprobe程序允许在执行内核函数之前插入BPF程序。当内核执行到kprobe挂载的内核函数时,先运行BPF程序,BPF程序运行结束后,返回继续开始执行内核函数。下面是一个使用kprobe的bcc程序示例,功能是监控内核函数kfree_skb函数,当此函数触发时,记录触发它的进程pid,进程名字和触发次数,并打印出触发此函数的进程pid,进程名字和触发次数:

#!/usr/bin/python3

# coding=utf-8

from __future__ import print_function

from bcc import BPF

from time import sleep

# define BPF program

bpf_program = “”“

#include 《uapi/linux/ptrace.h》

struct key_t{

u64 pid;

};

BPF_HASH(counts, struct key_t);

int trace_kfree_skb(struct pt_regs *ctx) {

u64 zero = 0, *val, pid;

pid = bpf_get_current_pid_tgid() 》》 32;

struct key_t key = {};

key.pid = pid;

val = counts.lookup_or_try_init(&key, &zero);

if (val) {

(*val)++;

}

return 0;

}

”“”

def pid_to_comm(pid):

try:

comm = open(“/proc/%s/comm” % pid, “r”).read().rstrip()

return comm

except IOError:

return str(pid)

# load BPF

b = BPF(text=bpf_program)

b.attach_kprobe(event=“kfree_skb”, fn_name=“trace_kfree_skb”)

# header

print(“Tracing kfree_skb.。。 Ctrl-C to end.”)

print(“%-10s %-12s %-10s” % (“PID”, “COMM”, “DROP_COUNTS”))

while 1:

sleep(1)

for k, v in sorted(b[“counts”].items(),key = lambda counts: counts[1].value):

print(“%-10d %-12s %-10d” % (k.pid, pid_to_comm(k.pid), v.value))

该bcc程序主要包括两个部分,一部分是python语言,一部分是c语言。python部分主要做的工作是BPF程序的加载和操作BPF程序的map,并进行数据处理。c部分会被llvm编译器编译为BPF字节码,经过BPF验证器验证安全后,加载到内核中执行。python和c中出现的陌生函数可以查下面这两个手册,在此不再赘述:

python部分遇到的陌生函数可以查这个手册: 点此跳转

c部分中遇到的陌生函数可以查这个手册: 点此跳转

需要说明的是,该BPF程序类型是kprobe,它是在这里进行程序类型定义的:

b.attach_kprobe(event=“kfree_skb”, fn_name=“trace_kfree_skb”)

b.attach_kprobe()指定了该BPF程序类型为kprobe;

event=“kfree_skb”指定了kprobe挂载的内核函数为kfree_skb;

fn_name=“trace_kfree_skb”指定了当检测到内核函数kfree_skb时,执行程序中的trace_kfree_skb函数;

BPF程序的第一个参数总为ctx,该参数称为上下文,提供了访问内核正在处理的信息,依赖于正在运行的BPF程序的类型。CPU将内核正在执行任务的不同信息保存在寄存器中,借助内核提供的宏可以访问这些寄存器,如PT_REGS_RC。

程序运行结果如下:

e2411330-a100-11eb-8b86-12bb97331649.png

3.3 kretprobes

相比于内核探针kprobe程序,kretprobe程序是在内核函数有返回值时插入BPF程序。当内核执行到kretprobe挂载的内核函数时,先执行内核函数,当内核函数返回时执行BPF程序,运行结束后返回。

以上面的BPF程序为例,若要使用kretprobe,可以这样修改:

b.attach_kretprobe(event=“kfree_skb”, fn_name=“trace_kfree_skb”)

b.attach_kretprobe()指定了该BPF程序类型为kretprobe,kretprobe类型的BPF程序将在跟踪的内核函数有返回值时执行BPF程序;

event=“kfree_skb”指定了kretprobe挂载的内核函数为kfree_skb;

fn_name=“trace_kfree_skb”指定了当内核函数kfree_skb有返回值时,执行程序中的trace_kfree_skb函数;

4. 内核静态跟踪点 tracepoint

tracepoint是内核静态跟踪点,它与kprobe类程序的主要区别在于tracepoint由内核开发人员在内核中编写和修改。

4.1 tracepoint 程序的优缺点

优点 跟踪点是静态的,ABI更稳定,不随内核版本的变化而致不可用。

缺点 跟踪点是内核人员添加的,不会全面涵盖内核的所有子系统。

4.2 tracepoint 可用跟踪点

系统中所有的跟踪点都定义在/sys/kernel/debug/traceing/events目录中:

e24d14fa-a100-11eb-8b86-12bb97331649.png

使用命令perf list 也可以列出可使用的tracepoint点:

e2629bc2-a100-11eb-8b86-12bb97331649.png

对于bcc程序来说,以监控kfree_skb为例,tracepoint程序可以这样写:

b.attach_tracepoint(tp=“skb:kfree_skb”, fn_name=“trace_kfree_skb”)

bcc遵循tracepoint命名约定,首先是指定要跟踪的子系统,这里是“skb:”,然后是子系统中的跟踪点“kfree_skb”:

e29048b0-a100-11eb-8b86-12bb97331649.png

5. 总结

本文主要介绍了保证BPF程序安全的BPF验证器,然后以BPF程序的工具集BCC为例,分享了kprobes和tracepoints类型的BPF程序的使用及程序编写示例。本文分享的是内核跟踪,那么用户空间程序该如何跟踪呢,这将在后面的文章中逐步分享,感谢阅读。

参考资料:

若未安装bcc,请参考下方网址进行安装;

https://github.com/iovisor/bcc/blob/master/INSTALL.md

bcc程序编写指导手册

https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md

参考书《Linux内核观测技术 BPF》

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 虚拟机
    +关注

    关注

    1

    文章

    968

    浏览量

    30176
  • python
    +关注

    关注

    57

    文章

    4857

    浏览量

    89579
  • BCC
    BCC
    +关注

    关注

    0

    文章

    10

    浏览量

    7746
  • BPF
    BPF
    +关注

    关注

    0

    文章

    26

    浏览量

    4633

原文标题:梁金荣:使用eBPF追踪LINUX内核

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    基于 DR1M90 的 Linux-RT 内核开发:从编译配置到 GPIO / 按键应用实现(1)

    本手册由创龙科技研发,针对 DR1M90,详述 Linux-RT 实时内核开发:含实时性测试(LinuxLinux-RT 对比、CPU 空载 / 满负荷 / 隔离状态测试)、
    的头像 发表于 12-02 10:38 220次阅读
    基于 DR1M90 的 <b class='flag-5'>Linux</b>-RT <b class='flag-5'>内核</b>开发:从编译配置到 GPIO / 按键应用实现(1)

    Linux内核printk日志级别全解析:从参数解读到实操配置

    一、开篇:一个命令引出的核心问题 在 Linux 终端执行 cat /proc/sys/kernel/printk,你可能会看到这样的输出: 这串数字不是随机的,而是内核日志系统的“核心配置开关
    的头像 发表于 11-20 15:54 1248次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>printk日志级别全解析:从参数解读到实操配置

    重磅升级!迅为iTOP-Hi3403开发板SDK全面升级至Linux 6.6内核

    【重磅升级!迅为iTOP-Hi3403开发板SDK全面升级至Linux 6.6内核
    的头像 发表于 11-18 13:34 693次阅读
    重磅升级!迅为iTOP-Hi3403开发板SDK全面升级至<b class='flag-5'>Linux</b> 6.6<b class='flag-5'>内核</b>

    deepin亮相2025中国Linux内核开发者大会

    11 月 1 日,第二十届中国 Linux 内核开发者大会(CLK)在深圳举办。CLK 作为国内 Linux 内核领域极具影响力的峰会,由清华大学、Intel、华为、阿里云、富士通南大
    的头像 发表于 11-05 17:59 623次阅读

    RK3506开发板Xenomai内核RT-Linux实时性系统适配教程与性能实测,实测仅7μs稳定延时

    本文基于触觉智能RK3506核心板/开发板,介绍Xenomai内核RT-Linux实时性系统适配,并附性能实测。简介与实测数据Xenomai简介XEnomai是一个实时子系统,可与Linux
    的头像 发表于 09-18 14:21 883次阅读
    RK3506开发板Xenomai<b class='flag-5'>内核</b>RT-<b class='flag-5'>Linux</b>实时性系统适配教程与性能实测,实测仅7μs稳定延时

    Linux内核参数调优方案

    在高并发微服务环境中,网络性能往往成为K8s集群的瓶颈。本文将深入探讨如何通过精细化的Linux内核参数调优,让你的K8s节点网络性能提升30%以上。
    的头像 发表于 08-06 17:50 706次阅读

    基于eBPF的Kubernetes网络异常检测系统

    作为一名在云原生领域深耕多年的运维工程师,我见过太多因为网络问题导致的生产事故。传统的监控手段往往是事后诸葛亮,当你发现问题时,用户已经在抱怨了。今天,我将分享如何利用 eBPF 这一革命性技术,构建一套能够实时检测 Kubernetes 网络异常的系统。
    的头像 发表于 07-24 14:09 500次阅读

    如何配置和验证Linux内核参数

    Linux系统运维和性能优化中,内核参数(sysctl)的配置至关重要。合理的参数调整可以显著提升网络性能、系统稳定性及资源利用率。然而,仅仅修改参数是不够的,如何验证这些参数是否生效同样关键。
    的头像 发表于 05-29 17:40 785次阅读

    手把手教你如何调优Linux网络参数

    在高并发网络服务场景中,Linux内核的默认网络参数往往无法满足需求,导致性能瓶颈、连接超时甚至服务崩溃。本文基于真实案例分析,从参数解读、问题诊断到优化实践,手把手教你如何调优Linux
    的头像 发表于 05-29 09:21 644次阅读

    Linux内核编译失败?移动硬盘和虚拟机的那些事儿

    Linux开发中,编译内核是一项常见任务,但不少开发者在移动硬盘或虚拟机环境下尝试时会遭遇失败。本文将简要探讨这些问题的成因,并介绍一些虚拟机使用技巧,帮助大家更好地应对相关问题。在移动硬盘里编译
    的头像 发表于 04-11 11:36 729次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>编译失败?移动硬盘和虚拟机的那些事儿

    树莓派4 性能大比拼:标准Linux与实时Linux 4.19内核的延迟测试

    引言本文是对我之前关于RaspberryPi3同一主题的帖子的更新。与之前的帖子一样,我使用的是随Raspbian镜像提供的标准内核,以及应用了RT补丁的相似内核版本。对于实时版,我
    的头像 发表于 03-25 09:39 656次阅读
    树莓派4 性能大比拼:标准<b class='flag-5'>Linux</b>与实时<b class='flag-5'>Linux</b> 4.19<b class='flag-5'>内核</b>的延迟测试

    利用eBPF程序绕过内核以加速存储访问

    随着微秒级NVMe存储的蓬勃发展,Linux内核存储栈的开销几乎是存储访问时间的两倍,已经成为性能瓶颈。
    的头像 发表于 03-01 16:09 880次阅读
    利用<b class='flag-5'>eBPF</b>程序绕过<b class='flag-5'>内核</b>以加速存储访问

    腾讯云内核团队修复Linux关键Bug

    腾讯云操作系统(Tencent OS)内核团队近日在Linux社区取得了显著成果。他们提交的两项改进方案,成功解决了自2021年以来一直困扰众多一线厂商,并在近期让多个Linux顶级
    的头像 发表于 12-31 10:58 915次阅读

    嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-Linux内核移植之内核简介

    学到本章节,大家应该对Linux操作系统都有了一定的了解,但可能还不知道我们拿到手的内核源码都经历了什么。linux有一个庞大的开源社区,每个人都可以向开源社区提交代码。由于linux
    发表于 12-16 13:08

    飞凌嵌入式ElfBoard ELF 1板卡-Linux内核移植之内核简介

    学到本章节,大家应该对Linux操作系统都有了一定的了解,但可能还不知道我们拿到手的内核源码都经历了什么。linux有一个庞大的开源社区,每个人都可以向开源社区提交代码。由于linux
    发表于 12-13 09:03