首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【性能工程 - eBPF 技术】什么是 kprobe 和 uprobe?一文详解 kprobe 和 uprobe 奥秘

【性能工程 - eBPF 技术】什么是 kprobe 和 uprobe?一文详解 kprobe 和 uprobe 奥秘

作者头像
Lokinli
发布2025-07-20 08:20:15
发布2025-07-20 08:20:15
3270
举报
文章被收录于专栏:以终为始以终为始

kprobe(内核动态探测)

  • 定义与作用
    • kprobe 是一种用于在内核空间进行动态探测的机制。它允许开发者在不修改内核源代码的情况下,在内核函数的特定位置插入探测点。例如,可以在系统调用的入口或出口处插入 kprobe,这样就能捕获系统调用的相关信息,如参数、返回值等。
  • 工作原理
    • 当在一个内核函数上设置 kprobe 时,内核会在该函数的入口处插入一个断点。【这就是通过 eBPF 内核态程序完成的事情】当处理器执行到这个断点时,会触发一个预定义的处理程序(也称为探测函数)。这个处理程序可以收集关于被探测函数的各种信息,如函数的参数值。
      • 例如,在sys_open系统调用函数入口设置 kprobe,当进程执行open系统调用时,就会触发 kprobe 的处理程序,从而可以获取到open系统调用的参数,如文件名、打开模式等。
  • 应用场景(可跳过)
    • 性能分析:可以用于分析内核函数的执行时间,确定哪些内核函数是性能瓶颈。【像现在的 eBPF 工具, BCC 的一些 tools 等。】例如,通过在关键的内核调度函数上设置 kprobe,统计每个函数调用的时间开销,进而优化内核性能。
    • 故障排查:在系统出现内核相关的故障时,如内核崩溃或者异常行为,kprobe 可以帮助定位问题。例如,在可能导致内核错误的函数周围设置 kprobe,收集函数执行前后的状态信息,以确定故障原因。
  • 限制(可跳过)
    • 由于 kprobe 是在内核空间进行操作,使用不当可能会导致内核不稳定甚至崩溃。例如,如果在一个频繁调用的内核关键函数上设置了一个复杂的、耗时的 kprobe 处理程序,可能会影响系统的整体性能和稳定性。【这个应该不能算是限制,只能说是需要权衡的点】
  • 类型有哪一些?
    • kprobes可以插入到内核的几乎任何指令位置,当内核执行到该探测点时,会触发相应的处理函数,用户可通过此函数收集内核函数执行的相关信息【理论上,所有的内核函数都可以插桩】,如当前的函数名、函数处理的参数以及函数的返回值等,也可以获取到寄存器甚至全局数据结构的信息。
    • kretprobes(return probes)在指定的内核函数返回时才被执行,它建立在 kprobes 机制之上,主要用于探测内核函数或者系统调用的返回值以及计算函数执行耗时等。其工作原理是在函数入口处建立一个 kprobe,当函数被调用且该探测点被命中时,保存返回地址并替换为 “trampoline” 地址,当函数执行返回指令时,控制权传递给 “trampoline” 并触发探测,进而调用用户指定的返回处理程序。
  • 如何查看我们可以使用 kprobe 跟踪的函数?
    • 【既然理论上,所有的内核函数都可以跟踪,那我们查看内核源码,找到我们感兴趣的内核函数就可以了。】
    • 简单列一下方法:(建议跳过,基本就是一想就可以想到的方法)
      • 通过内核文档和头文件查看
        • 内核文档:Linux 内核文档是一个很好的起点。在内核源代码目录下的Documentation文件夹中,有关于 kprobe 相关的文档。这些文档可能会提及一些典型的可被跟踪的函数类别,例如系统调用相关函数(如sys_readsys_write等)、常见的内核调度函数(如schedule)以及设备驱动相关的核心函数等。虽然文档不会列出所有可跟踪的函数,但可以为你提供一些常见的目标函数示例。
        • 头文件:查看相关的内核头文件可以帮助你发现可跟踪的函数。例如,系统调用的函数原型通常定义在<sys/syscall.h>等头文件中。通过查看这些头文件中的函数声明,你可以找到系统调用相关的函数,这些函数一般都是可以使用 kprobe 进行跟踪的。另外,对于设备驱动相关的函数,在对应的设备驱动头文件(如linux/netdevice.h用于网络设备驱动相关函数)中也可以找到许多潜在的跟踪目标。
      • 利用工具辅助查看
        • SystemTap:SystemTap 是一个强大的动态跟踪工具,它基于 kprobe 等底层机制构建。虽然 SystemTap 本身不是直接用于查看可跟踪函数,但可以通过它来间接发现。例如,SystemTap 脚本可以在运行时查找内核中的符号(函数和变量),通过编写简单的 SystemTap 脚本,如查找所有以sys_开头的函数(可能是系统调用相关函数),就可以发现一些潜在的可跟踪函数。
        • ftrace:ftrace 是内核自带的一个函数跟踪工具。它可以帮助你查看哪些函数在内核中有跟踪点。ftrace 可以通过/sys/kernel/ftrace目录下的文件进行操作。例如,在available_filter_functions文件中,可以找到能够被跟踪的函数列表。虽然 ftrace 和 kprobe 不完全相同,但其中列出的许多函数也是可以使用 kprobe 进行跟踪的。不过需要注意的是,这个列表可能会受到内核配置和模块加载情况的影响。
      • 从应用场景和内核模块功能推测
        • 性能分析场景:如果你的目的是进行性能分析,那么可以从关键的性能相关的内核模块和函数入手。例如,对于网络性能分析,可以关注netfilter模块中的函数(如iptables相关的钩子函数)、网络协议栈相关函数(如tcp_rcvudp_recvmsg等)。这些函数在处理网络流量过程中起到关键作用,是很可能使用 kprobe 进行跟踪的目标。
        • 系统调用跟踪场景:如果想跟踪系统调用相关的行为,那么所有的系统调用函数(如sys_opensys_closesys_read等)都是可以使用 kprobe 进行跟踪的。这些函数的原型可以在内核源代码的arch/x86/entry/syscalls/syscall_64.tbl(对于 64 位 x86 系统)等文件中找到对应的系统调用号和函数名,进而使用 kprobe 进行跟踪。

uprobe(用户空间动态探测)

  • 定义与作用
    • uprobe 是用于在用户空间程序中进行动态探测的机制。它和 kprobe 类似,但主要应用于用户态的应用程序,允许在用户空间函数的特定位置插入探测点。比如,对于一个复杂的数据库应用程序,可以使用 uprobe 来监控特定数据库查询函数的调用情况。【简单来讲,就是跟踪用户编程的程序中函数】
  • 工作原理
    • 当在用户空间的一个函数上设置 uprobe 时,调试器会在目标函数的入口处插入一个断点(这个过程依赖于操作系统的调试支持)。当程序执行到这个断点时,会调用预先定义的处理程序。这个处理程序可以获取被探测函数的相关信息,如函数的参数、返回值等。
      • 例如,在一个 C++ 应用程序的vector::push_back函数入口设置 uprobe,当程序执行push_back操作时,就会触发 uprobe 的处理程序,从而可以获取到被插入元素的值等信息。
  • 应用场景(可跳过)
    • 应用程序性能分析可以用于分析用户空间应用程序中函数的执行时间、调用频率等性能指标。例如,对于一个 Web 服务器应用程序,通过在处理 HTTP 请求的函数上设置 uprobe,可以分析每个请求的处理时间,优化服务器性能。
    • 软件调试和监控:帮助开发者调试用户空间应用程序,特别是在大型复杂软件中,定位函数调用的异常情况。例如,在一个具有多个模块的图形处理软件中,通过 uprobe 监控模块间函数调用的参数传递是否正确。
  • 限制
    • 只能用于用户空间的应用程序,无法直接用于探测内核函数。【这个点也不能说限制,本来功能也不是为了插桩内核函数】并且,它依赖于应用程序的调试信息和符号表,如果应用程序没有这些信息(例如,经过高度优化的、去除了符号表的二进制文件),uprobe 的设置可能会受到限制。

声明

各种资料掺杂在一起的,然后让 AI 帮忙整理了一下,不保证没有错误,有错误请 call me。

还有就是一些个人笔记。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • kprobe(内核动态探测)
  • uprobe(用户空间动态探测)
  • 声明
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档