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

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

3天内不再提示

使用Ftrace研究Linux内核

Linux阅码场 来源:Linux阅码场 作者:Linux阅码场 2022-05-05 10:00 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

说明背景

文档作为会议的记录和补充,会议主题是《使用Ftrace研究Linux内核》,主讲人谢欢。回放链接

基本内容

1、Ftrace整体框架

c19f5546-cc07-11ec-bce3-dac502259ad0.jpg

根据官方文档的定义,Ftrace是一个内部跟踪器,旨在帮助系统的开发者和设计者去观测内核的运行。它可以被用于调试或分析发生在用户空间之外的延迟和性能问题。随着发展,目前已经演变成为一个基础的调试框架(支持多个不同类型的trace功能)。 直观理解有两层含义:一是提供函数钩子的基础设施,二是基于tracefs文件系统的trace框架。
  • function tracer:在函数头挂钩子函数

  • function graph tracer:可以带时间戳函数执行流打印

  • kprobe:一般是挂在函数入口点,用于获取参数

  • trace event:函数执行时调用静态的钩子函数

  • kretprobe:通常是函数出口点,执行钩子函数

2、使用方式

c1b63996-cc07-11ec-bce3-dac502259ad0.jpg

Ftrace通过tracefs文件系统的控制文件来进行调试。如果内核构建阶段配置ftrace,默认会挂载tracefs到/sys/kernel/tracing,也可以在运行环境手动挂载

c1c8a69e-cc07-11ec-bce3-dac502259ad0.png

接下来的内容我会根据课程介绍,整理出ftrace不同功能的使用案例,一些问答和和观点以及个人对课程总结。

function tracer使用

case01: 过滤"vfs_open"函数

c1dd2f06-cc07-11ec-bce3-dac502259ad0.png

观察结果:图示能看到所有执行vfs_open的跟踪信息。

c1f35c68-cc07-11ec-bce3-dac502259ad0.png

function graph tracer使用

case01: 函数"vfs_open"的执行时间


		

echo vfs_open > ./set_ftrace_filter # 过滤要跟踪的函数

echo function_graph > ./current_tracer # 设置当前使用的tracerecho 1 > ./options/funcgraph-proc # 启用进程TASK/PID打印cp trace /test.txt && cat /test.txt

c211ac4a-cc07-11ec-bce3-dac502259ad0.jpg

观察结果:查看到vfs_open被执行的调试信息包括TASK/PID,函数的执行时间在,接口名。原理上是通过在函数的入口点和出口点(kprobe/kretprobe)挂钩子来实现的。

case02: 函数"vfs_open"向下执行流

echo > ./set_ftrace_filter # 不使用过滤!!!echo vfs_open > ./set_graph_function #  使用函数图表echo function_graph > ./current_tracer # 过滤要跟踪的函数echo 1 > ./options/funcgraph-proc # 打印进程TASK/PIDecho 1 > ./options/funcgraph-tail # 尾部注释(方便观察)cp trace /test.txt && cat /test.txt

c227c1ce-cc07-11ec-bce3-dac502259ad0.jpg

观察结果:vfs_open被执行时,能看到向下的执行流程,其中涉及到的函数调用和相关信息会打印出来。

kprobe event

case01: 查看"vfs_open"当前打开文件名

# 理论计算:# $arg1, 第一个参数# +0x8($arg1), 地址偏移+0x8# +0x70(+0x8($arg1)), 相当与C语言的 *(*($arg1 + 0x8) + 0x70)
echo 'p vfs_open name=+0x70(+0x8($arg1)):string namep=+0(+0x60(+0x8($arg1))):string' > ./kprobe_eventsecho 1 > ./events/kprobes/p_vfs_open_0/enableecho > trace && cat /test.txtcp trace /test.txt && cat /test.txt

c23dbad8-cc07-11ec-bce3-dac502259ad0.jpg

观察结果:图示看到一些vfs_open函数的kprobe事件,name是当前被查看的文件名。kprobe通过参数加地址偏移计算拿到特定成员的地址

case02: 捕获"vfs_open"查看指定文件的信息的事件

# 功能: 利用filter和trigger文件root@debian:/sys/kernel/debug/tracing# ls ./events/kprobes/p_vfs_open_0/enable filter format hist id inject trigger
# 格式: kprobe eventroot@debian:/sys/kernel/debug/tracing# cat ./events/kprobes/p_vfs_open_0/format
echo 'p vfs_open name=+0x70(+0x8($arg1)):string namep=+0(+0x60(+0x8($arg1))):string' > ./kprobe_eventsecho 1 > ./events/kprobes/p_vfs_open_0/enable # 过滤包含"test"字段的文件的事件echo 'name ~ "*test*"' > ./events/kprobes/p_vfs_open_0/filterecho > trace && cat /test.txtecho 'stacktrace if name ~ "*test*"' > ./events/kprobes/p_vfs_open_0/trigger  # 包含"test"字段的文件的事件会触发"stacktrace"堆栈打印

trace event

cat /sys/kernel/debug/tracing/available_events # 查看当前支持的跟踪事件列表

case01: 打开驱动中跟踪节点

echo 1 > /sys/kernel/debug/tracing/events/gsgpu/enable && echo 0 > /sys/kernel/debug/tracing/trace && /root/run_test.sh ; cp /sys/kernel/debug/tracing/trace /test.txt && echo 0 > /sys/kernel/debug/tracing/events/gsgpu/enablecat /test.txt

case02: 通过filter过滤事件

echo 0 > /sys/kernel/debug/tracing/events/gsgpu/enable && echo 1 > /sys/kernel/debug/tracing/events/gsgpu/gsgpu_bo_move/enable && echo 0 > /sys/kernel/debug/tracing/trace && echo "bo_size >= 50000" > /sys/kernel/debug/tracing/events/gsgpu/gsgpu_bo_move/filter && /root/run_test.sh ; cp /sys/kernel/debug/tracing/trace /test.txt && echo 0 > /sys/kernel/debug/tracing/events/gsgpu/gsgpu_bo_move/filtercat /test.txt

case03: 通过trigger查看栈回溯

echo 0 > /sys/kernel/debug/tracing/events/gsgpu/enable && echo 1 > /sys/kernel/debug/tracing/events/gsgpu/gsgpu_bo_move/enable && echo 0 > /sys/kernel/debug/tracing/trace && echo 'stacktrace' > /sys/kernel/debug/tracing/events/gsgpu/gsgpu_bo_move/trigger && /root/run_test.sh ; cp /sys/kernel/debug/tracing/trace /test.txt && echo '!stacktrace' > /sys/kernel/debug/tracing/events/gsgpu/gsgpu_bo_move/trigger && cat /test.txt

objtrace

case01:观察对象数据在函数中流动

源码位置:https://github.com/x-lugoo/linux/tree/objtrace-v9

[root@JeffXie tracing]# cat ./events/kprobes/p_bio_add_page_0/trigger Available triggers: traceon traceoff snapshot stacktrace enable_event disable_event hist objtrace
cd /sys/kernel/debug/tracing/echo 'p bio_add_page arg1=$arg1 arg2=$arg2' > ./kprobe_eventsecho 'objtracearg1,0x285 if comm == "cat"' > ./events/kprobes/p_bio_add_page_0/trigger# du -sh /test.txt // 12Kcat /test.txt > /dev/nullcat ./trace

c252437c-cc07-11ec-bce3-dac502259ad0.jpg

观察结果:参数arg1对应object对象,由于有kprobe匹配到目标参数达到触发条件,我看到图示中打印的调试信息。这样就可以观察到指定接口的参数在内核函数中是怎样流动的

一些观点

  • 1、ftrace很多功能在国内使用不充分,比如tracer网上资料少,ftrace功能很强大,可挖掘的潜力大。像是大家对shell的使用,如果大家能积累更多的案例,这样能更好的普及和使用。

  • 2、ftrace和正常的日志环形缓冲区不同,如果大量日志向同一个缓冲区输入,一会导致信息混乱,二是容易覆盖有效数据。使用ftrace的过滤等功能,可以更好的解决此类问题(适用更加复杂的业务场景)。补充ftrace其他功能:自动保存结果输出到文件;生成直方图;触发其他事件;等等。

  • 3、ftrace对内核的通用性还是比较强的,相比ebpf来说ftrace对于低版本的内核更加友好。

  • 4、ftrace的用户群体大,但是名声没有ebpf的功能大。

  • 5ftrace的tracer在linux中使用shell脚本来实现,如果想要观察和定位,使用这种手段方便;如果转发类或者做业务相关的,推荐使用ebpf比较多。可以根据各自优势应用到不同的场景,也可以两者结合使用。

一些问答

perf/ftrace/ebpf关系

基于kprobe的ebpf通过 fd找到字节码程序,当perf使用相同功能的时候,可以依据 fd来找到这个字节码程序。基于kprobe的ebpf本质上是基于ftrace, 使用ftrace框架来调用字节码程序

#使用bpftrace工具将ebpf程 序挂载到"kprobe:do_ nanosleep"bpftrace -e 'kprobe:do_nanosleep { printf("PID %d sleeping... ", pid); }'

kprobe和function trace的钩子有什么区别?

基本相同,kprobe的钩子函数会做更多的解析工作,例如解析更多的 field(例如argN或stackN等)

什么是no trace函数?

如果函数本身参与ftrace功能,不能用于trace(避免递归) 这样的函数一般都是no trace。

uprobe是用什么实现的?

uprobe在用户层,基于断点指令来实现。

ftrace对性能影响多大?

看如何使用?如果对所有函数使用function tracer,如果只使用一个性能事件性能消耗很小。

如果从学习内核的角度来讲,怎样把ftrace作为一个辅助的工具来上手内核?

在调试内核的时候,通常使用printk/printf来使用,使用ftrace的前提要戒掉这个习惯,然后使用ftrace工具来调试。

对于可靠性和安全性比较高的领域,对于ftrace是不是要慎用一些?

是的,对原理理解要求比较高一些。对原理比较清楚的话,能很好的缩小ftrace的使用范围,来进一步降低对系统的性能消耗。

如何评估这些调试工具的开销?

正确对待ftrace是一个辅助工具,前提还是要对代码比较熟悉,ftrace辅助对代码的观察。

ftrace这样的工具好处?

使用在不破坏内核的情况下,提供一个对内核可观测手段;提供基础的tracer功能,灵活运用好tracer功能对分析问题帮助;perf工具将各种类型的挂载点收入囊中,一统江湖。

linux内核中有这么多钩子?都有什么局限,如何选择

看具体想使用哪些功能,比如查看函数怎么执行,选择function tracer;比如查看某一个函数的参数,使用kprobe挂载点对应的钩子函数不一样的。

ftrace的tracer在linux中使用shell脚本来实现,如果想要观察和定位,使用这种手段方便;如果转发类或者做业务相关的,推荐使用ebpf比较多

各有优势,应用到不同的场景,也可以两者结合使用。

嵌入式场景,内存资源比较紧张的时候适用么?

内存消耗比较小。也可以设置,buffer可以调小一些。

ftrace在性能消耗比ebpf更小么?

也不一定,看使用那部分功能。

有没有推荐的日志化性能分析的图形工具?

tracecmd和KernelShark。

个人总结

内核源码中放置很多静态跟踪节点,这些节点可以被关联到对应的回调函数。当我想要调试某个子系统/模块时,通过debug系统将对应的节点开启(将回调函数挂钩子到静态跟踪点上,与之关联),这样内核在执行到跟踪点位置的时候会调用钩子函数,最终执行结果将被输出写到一个环形日志缓存区里,通过debug系统查看信息。

作为一种内核层面的调试手段,trace event利用了ftrace框架,算是ftrace的一个应用吧。当我想要调试某一个模块,开启对应的节点就好了,trace event基于现有的跟踪节点(一般是写代码的添加好的)效率高些,或者解决新的bug时将关键调试信息固化到调试系统里。

从做工作的角度,我能体会到的是trace event工具能带来工作效率的提升。从学习的角度,我相信使用ftrace工具能更加方便观测内核

审核编辑 :李倩


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

    关注

    4

    文章

    1436

    浏览量

    42480
  • Linux
    +关注

    关注

    88

    文章

    11627

    浏览量

    217888

原文标题:会议记录|使用Ftrace研究Linux内核

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

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

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

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

    本手册由创龙科技研发,针对 DR1M90,详述 Linux-RT 实时内核开发:含实时性测试(LinuxLinux-RT 对比、CPU 空载 / 满负荷 / 隔离状态测试)、
    的头像 发表于 12-02 10:38 143次阅读
    基于 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 1232次阅读
    <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 685次阅读
    重磅升级!迅为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 612次阅读

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

    本文基于触觉智能RK3506核心板/开发板,介绍Xenomai内核RT-Linux实时性系统适配,并附性能实测。简介与实测数据Xenomai简介XEnomai是一个实时子系统,可与Linux
    的头像 发表于 09-18 14:21 855次阅读
    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 703次阅读

    如何单独编译linux内核

    那套sdk?纯linux sdk编译方法见readmehttps://github.com/kendryte/k230_linux_sdk/ make linux
    发表于 07-11 08:06

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

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

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

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

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

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

    基于OpenSBI的linux nommu实现

    Linux内核6.10提供了对没有mmu的riscv处理器工作在S模式下的内核的支持,本文介绍基于OpenSBI的linuxnommu的实现,供大家参考。1、OpenSBI介绍SBI
    的头像 发表于 02-08 13:43 1048次阅读
    基于OpenSBI的<b class='flag-5'>linux</b> nommu实现

    升级centos7内核版本

    先查看当前内核版本 ~] #uname -a Linux localhost.localdomain 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 1659
    的头像 发表于 01-02 10:41 998次阅读

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

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

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

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

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

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