理解并使用Linux 内核中的 Tracepoint
理解并使用Linux 内核中的 Tracepoint
1. 引言
1.1 为什么需要 Tracepoint?
在内核调试与性能分析中,传统的 printk
方法虽然简单直接,但存在几个显著的局限性:
- 日志噪音:printk 会将所有输出无差别地记录到系统日志或控制台,这会导致大量无关紧要的信息混杂其中,增加了排查问题的难度。
- 性能开销:频繁调用 printk 可能会对系统的实时性能造成负面影响,特别是在高并发场景下。
- 侵入性强:为了添加或移除 printk,往往需要修改源代码,重新编译并加载新的内核模块,这不仅增加了工作量,还可能引入新的错误。
相比之下,Tracepoint
提供了一种更为高效、灵活且低侵入性的方法来跟踪特定事件。它允许开发者和系统管理员在不影响正常业务逻辑的前提下,动态地开启或关闭跟踪功能,收集精确的时间戳和上下文信息,从而有效地减少了对系统性能的影响,并且能够更好地定位和解决复杂的问题。
1.2 什么是 Tracepoint?
Tracepoint
是 Linux 内核提供的一个轻量级机制,用于在不改变代码逻辑的情况下,通过预先定义好的钩子点(hook points
)监控内核行为。这些钩子点是在内核编译时静态定义的,作为源码的一部分存在于特定的关键路径上。当内核执行流经过这些位置时,如果事先注册了监听器,则会触发对应的回调函数,使得用户可以在不修改内核代码的情况下,灵活地收集所需的数据或执行额外的操作。
每个 Tracepoint 实际上代表了一个可以被激活或停用的开关,这意味着它们可以在运行时根据需要选择性地启用,以最小化不必要的性能损失。此外,由于 Tracepoint 的设计考虑到了多处理器环境下的同步问题,因此它们也适用于 SMP(对称多处理)系统中的并发事件追踪。
1.3 内核中内置的 Tracepoint 简介
Linux 内核中已经内置了大量的 Tracepoint
,涵盖了从文件系统操作到网络协议栈等多个方面。要查看当前系统中存在的所有 Tracepoint,可以使用如下命令:
ls /sys/kernel/debug/tracing/events/
该目录下的每一个子文件夹对应着一个不同的子系统或功能区域,例如 ext4
文件夹包含了 ext4 文件系统相关的所有 Tracepoint。进一步深入到具体的子文件夹中,可以看到一系列以 .enable
结尾的文件,这些文件控制着相应 Tracepoint 的启用状态;而以 .format
结尾的文件则描述了该 Tracepoint 所携带的数据结构及其格式说明。
对于想要深入了解某个特定 Tracepoint 的用户来说,可以通过阅读其 .format
文件了解如何解析由这个 Tracepoint 产生的数据。同时,也可以利用其他工具如 trace-cmd
或者 Ftrace 来更方便地管理和分析 Tracepoint 数据。
2. Tracepoint 的工作原理
Tracepoint 是一种在内核编译阶段静态定义的机制,作为内核源码的一部分存在。这些预先定义的钩子点(hook points)位于内核代码的关键路径上。当内核运行到这些位置时,如果该位置被注册了监听器,则会触发预先设定的回调函数。Tracepoint
允许开发者或管理员在不修改内核逻辑的情况下动态地附加回调函数,以便收集所需信息或执行额外操作。
为了更清楚地理解 Tracepoint 的工作方式,我们以 ext4/ext4_drop_inode
跟踪点为例来说明。下面的代码片段展示了如何在 ext4 文件系统中定义一个名为 ext4_drop_inode
的 Tracepoint:
// 定义 ext4_drop_inode Tracepoint
TRACE_EVENT(ext4_drop_inode,TP_PROTO(struct inode *inode, int drop), // 参数列表TP_ARGS(inode, drop), // 参数传递TP_STRUCT__entry(__field(dev_t, dev) // 定义记录字段__field(ino_t, ino)__field(int, drop)),TP_fast_assign(__entry->dev = inode->i_sb->s_dev; // 快速赋值__entry->ino = inode->i_ino;__entry->drop = drop;),TP_printk("dev %d,%d ino %lu drop %d", // 格式化输出MAJOR(__entry->dev), MINOR(__entry->dev),(unsigned long) __entry->ino, __entry->drop)
);// 在 ext4_drop_inode 函数中调用 Tracepoint
static int ext4_drop_inode(struct inode *inode)
{int drop = generic_drop_inode(inode);if (!drop)drop = fscrypt_drop_inode(inode);trace_ext4_drop_inode(inode, drop); // 触发 Tracepointreturn drop;
}
在这个例子中,TRACE_EVENT
宏用于创建一个新的 Tracepoint,具体步骤如下:
- 参数声明 (
TP_PROTO
):指定 Tracepoint 接受的参数类型。 - 参数传递 (
TP_ARGS
):将实际参数传递给 Tracepoint。 - 结构体定义 (
TP_STRUCT__entry
):定义 Tracepoint 将保存的数据结构及其成员。 - 快速赋值 (
TP_fast_assign
):提供一个简短的代码块,用于快速填充上述结构体中的字段。 - 格式化输出 (
TP_printk
):定义如何将 Tracepoint 数据格式化为人类可读的字符串形式。
每当 ext4_drop_inode
函数被执行时,都会调用 trace_ext4_drop_inode()
来触发相应的 Tracepoint。此时,如果有任何监听器注册到了这个 Tracepoint 上,那么这些监听器所关联的回调函数就会被执行,从而可以进行日志记录或其他操作。
3. 如何在内核模块中使用 Tracepoint
为了让用户能够方便地利用 Tracepoint 进行监控,内核模块提供了一种机制来注册和注销回调函数,从而实现对特定事件的监听。
3.1 注册和注销回调函数
- 注册:通过
tracepoint_probe_register()
函数。 - 注销:通过
tracepoint_probe_unregister()
函数。
3.2 示例代码
下面的例子演示了如何创建一个简单的内核模块来捕捉 ext4/ext4_drop_inode
事件:
#include <linux/module.h>
#include <linux/tracepoint.h>
#include <linux/fs.h>
#include <linux/ext4.h>/* 用于管理感兴趣的tracepoint,即我要使用的tracepoint */
struct interest_tracepoint
{void *callback; /* 指向tracepoint要执行的回调函数 */struct tracepoint *ptr; /* 对应tracepoint的指针 */char is_registered; /* 记录回调函数是否已注册 */
};/* 用于生成一个struct interest_tracepoint结构体并初始化,参数: tracepoint_name */
#define INIT_INTEREST_TRACEPOINT(tracepoint_name) \static struct interest_tracepoint tracepoint_name##_tracepoint = {.callback = NULL, .ptr = NULL, .is_registered = 0};/* 该宏用于生成for_each_kernel_tracepoint的回调函数,前者用于遍历整个内核的tracepoint表 */
#define TRACEPOINT_FIND(tracepoint_name) \static void tracepoint_name##_tracepoint_find(struct tracepoint *tp, void *priv) \{ \if (!strcmp(#tracepoint_name, tp->name)) \{ \((struct interest_tracepoint *)priv)->ptr = tp; \return; \} \}/* 用于注销一个tracepoint的回调函数 */
static void clear_tracepoint(struct interest_tracepoint *interest)
{if (interest->is_registered){tracepoint_probe_unregister(interest->ptr, interest->callback, NULL);}
}/* 生成并初始化struct interest_tracepoint ext4_drop_inode */
INIT_INTEREST_TRACEPOINT(ext4_drop_inode)/* 生成ext4_drop_inode_tracepoint_find函数 */
TRACEPOINT_FIND(ext4_drop_inode)/* tracepoint: ext4_drop_inode触发时的回调函数 */
static void ext4_drop_inode_tracepoint_callback(void *data, struct inode *inode)
{/* 这里可以插入你需要的自定义逻辑,例如打印inode的详细信息 */pr_info("ext4_drop_inode called for inode: %ld\n", inode->i_ino);
}static int __init tracepoint_init(void)
{/* 在我们自己的struct interest_tracepoint中记录管理的tracepoint要调用的回调函数 */ext4_drop_inode_tracepoint.callback = ext4_drop_inode_tracepoint_callback;/* 使用for_each_kernel_tracepoint遍历并查找ext4_drop_inode的tracepoint */for_each_kernel_tracepoint(ext4_drop_inode_tracepoint_find, &ext4_drop_inode_tracepoint);/* 判断是否找到目标tracepoint */if (!ext4_drop_inode_tracepoint.ptr){pr_info("ext4_drop_inode's struct tracepoint not found\n");return 0;}/* 注册回调函数到tracepoint */tracepoint_probe_register(ext4_drop_inode_tracepoint.ptr, ext4_drop_inode_tracepoint.callback, NULL);ext4_drop_inode_tracepoint.is_registered = 1; /* 记录回调函数已注册 */return 0;
}static void __exit tracepoint_exit(void)
{clear_tracepoint(&ext4_drop_inode_tracepoint);
}module_init(tracepoint_init);
module_exit(tracepoint_exit);
MODULE_LICENSE("GPL");
注意,上述代码中的输出信息采用了更加直观的命名方式,以便于理解和维护。
3.3 验证
加载模块后,可以通过 dmesg
命令检查内核消息缓冲区,验证是否成功捕捉到了 ext4_drop_inode
事件:
dmesg | grep ext4_drop_inode
这一步骤有助于确认我们的模块是否按预期工作。
4. 在用户空间使用 Tracepoint
除了内核模块之外,用户还可以借助一系列强大的工具,如 trace-cmd
和 perf
,轻松捕获并分析 Tracepoint 事件。
4.1 使用 trace-cmd 捕获事件
以下是使用 trace-cmd
工具捕捉 ext4/ext4_drop_inode
事件的具体步骤:
-
启动事件捕获
sudo trace-cmd record -e ext4:ext4_drop_inode
-
触发事件(例如删除一个文件)
rm /path/to/file
-
查看捕获结果
trace-cmd report
输出示例:
rm-137270 [005] 333384.754465: ext4_drop_inode: device=8,2 inode=1357167 drop=1
5. 总结与延伸
与其他调试技术对比
技术 | 特点 | 应用场景 |
---|---|---|
Tracepoint | 静态定义、低开销、易于集成 | 实时性能监控、事件追踪 |
Kprobe | 动态插入、高度灵活 | 探索未知问题、深入调试 |
Ftrace | 全面而强大的跟踪框架 | 广泛的功能剖析与故障排除 |
eBPF | 高性能、动态编程 | 复杂业务逻辑下的实时响应 |
核心回顾
Tracepoint
作为一种轻量级的跟踪解决方案,在保证系统稳定性的同时,提供了极大的灵活性。它特别适用于那些需要持续监测和优化的应用场景,帮助开发者更好地理解系统行为。
扩展方向
- 结合
ftrace
使用,进一步挖掘内核活动的细节。 - 利用
bpftrace
或其他 eBPF 工具,探索更为复杂的监控策略,包括跨层数据关联和实时反馈。
相关文章:

理解并使用Linux 内核中的 Tracepoint
理解并使用Linux 内核中的 Tracepoint 1. 引言 1.1 为什么需要 Tracepoint? 在内核调试与性能分析中,传统的 printk 方法虽然简单直接,但存在几个显著的局限性: 日志噪音:printk 会将所有输出无差别地记录到系统日…...

centos7中Gbase8s数据库安装,以及数据导入遇到的一系列问题
centos7中Gbase8s数据库安装,以及遇到的一系列问题 以下是我在centos7上安装gbase8s数据库遇到的一系列问题,包括数据库安装,数据导入,数据连接,不能完全作为标准,只可作为类似问题参考,有问题…...

AW36518芯片手册解读(3)
接前一篇文章:AW36518芯片手册解读(2) 二、详述 3. 功能描述 (1)上电复位 当电源电压VIN降至预定义电压VPOR(典型值为2.0V)以下时,该设备会产生复位信号以执行上电复位操作&#x…...

MySQL的REPEATABLE READ事务隔离级别
本文隔离级别: T1内读T2的update数据 首先开两个事务(左二) 事务1修改成李四,提交 事务2再读还是张三,也就是说,记录的数据从事务开始时一直到结束,读的都是同一个版本,读不到T2未提交的此条记录修改&…...

sqoop的参数有哪些?
Sqoop 是一款用于在 Hadoop 与关系型数据库之间进行数据传输的工具,它有很多参数,可分为通用参数、导入参数和导出参数等,以下是一些常见的参数介绍: 通用参数 --connect 说明:指定要连接的关系型数据库的 JDBC URL。…...

动态规划<四> 回文串问题(含对应LeetcodeOJ题)
目录 引例 其余经典OJ题 1.第一题 2.第二题 3.第三题 4.第四题 5.第五题 引例 OJ 传送门Leetcode<647>回文子串 画图分析: 使用动态规划解决 原理:能够将所有子串是否是回文的信息保存在dp表中 在使用暴力方法枚举出所有子串,是…...

跨模态知识迁移:基于预训练语言模型的时序数据建模
在NLP和CV领域,通常通过在统一的预训练模型上进行微调,能够在各自领域的下游任务中实现SOTA(最先进)的结果。然而,在时序预测领域,由于数据量相对较少,难以训练出一个统一的预训练模型来覆盖所有…...

重温设计模式--职责链模式
文章目录 职责链模式的详细介绍C 代码示例C示例代码2 职责链模式的详细介绍 定义与概念 职责链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它旨在将请求的发送者和多个接收者解耦,让多个对象都有机会处理请求&a…...

git冲突解决
git冲突解决 最近遇到了一次git冲突的问题 起因是因为最近公司数据推送部分重构,负责重构的同事就改动了我的一小部分推送的代码,然后等我开发完合并到远程master的时候,报了merge冲突。我对于git工具确实不是很熟练,只是学习了…...

Java学习笔记(14)--面向对象编程
面向对象基础 学习资料来自多态 - Java教程 - 廖雪峰的官方网站 目录 面向对象基础 Override 多态 举个例子 覆写Object方法 调用super final 练习 小结 Override 在继承关系中,子类如果定义了一个与父类方法签名完全相同的方法,被称为覆写&…...

《Swift 字面量》
《Swift 字面量》 介绍 在 Swift 编程语言中,字面量是一种表示源代码中固定值的表达方式。字面量可以直接表示数字、字符串、布尔值等基本数据类型,为编程提供了简洁和直观的方式。Swift 支持多种类型的字面量,包括整数字面量、浮点数字面量…...

数据库 SQL 常用语句全解析
数据库 SQL 常用语句全解析 在数据库领域,SQL(Structured Query Language)作为标准语言,掌控着数据的查询、插入、更新与删除等关键操作。无论是新手入门数据库,还是经验丰富的开发者日常工作,熟练掌握 SQ…...

SQLite 命令
关于《SQLite 命令》的文章,我可以为您概述一些关键点。SQLite是一个轻量级的数据库管理系统,它被广泛用于各种应用程序中。SQLite命令主要分为两类:一类是SQL命令,另一类是SQLite特定的点命令。 SQL命令:这些命令用于…...

本地如何启动casdoor
1、下载代码 GitHub - casdoor/casdoor at v1.777.0 下载对应tag的代码,我这里选择的时v1.777.0版本 通过网盘分享的文件:casdoor-1.777.0.zip 链接: https://pan.baidu.com/s/1fPNqyJYeyfZnem_LtEc0hw 提取码: avpd 2、启动后端 1、使用goland编译…...

目标检测-R-CNN
R-CNN在2014年被提出,算法流程可以概括如下: 候选区域生成:利用选择性搜索(selective search)方法找出图片中可能存在目标的候选区域(region proposal) CNN网络提取特征:对候选区域进行特征提取(可以使用AlexNet、VGG等网络) 目…...

【持续更新】Github实用命令
Intro 最近高强度使用github,遂小计于此作为备忘。 Basic github是一个代码管理软件,能够track文件变动并且管理版本,是当代coding必不可少的工具。当你安装好github在本地以后,你可以通过以下命令初始化当前文件夹(…...

docker 容器的基本使用
docker 容器 一、docker是什么? 软件的打包技术,就是将算乱的多个文件打包为一个整体,打包技术在没有docker容器之前,一直是有这种需求的,比如上节课我把我安装的虚拟机给你们打包了,前面的这种打包方式是…...

css让按钮放在最右侧
要将 el-button 按钮放在最右侧,可以使用多种方法,具体取决于使用的布局方式和样式库。以下是几种常见的解决方案: 方法 1:使用 CSS Flexbox Flexbox 是一种非常灵活的布局方式,可以轻松实现水平或垂直对齐。你可以将…...

8K+Red+Raw+ProRes422分享5个影视级视频素材网站
Hello,大家好,我是后期圈! 在视频创作中,电影级的视频素材能够为作品增添专业质感,让画面更具冲击力。无论是广告、电影短片,还是品牌宣传,高质量的视频素材都是不可或缺的资源。然而ÿ…...

Linux网络——UDP的运用
Linux网络——UDP的运用 文章目录 Linux网络——UDP的运用一、引入二、服务端实现2.1 创建socket套接字2.2 指定网络接口并bind2.3 接收数据并处理2.4 整体代码2.5 IP的绑定的细节 三、用户端实现3.1 创建套接字3.2 指定网络接口3.3 发生数据并接收3.4 绑定问题 四、代码五、UD…...

项目亮点案例
其实对我来说是日常操作,但是如果在面试的时候面试者能把日常的事情总结好发出来,其实足矣。 想让别人认同项目,选取的示例需要包含以下要素: 亮点项目四要素:明确的目标,问题点,解决方法和结果…...

Retrofit源码分析:动态代理获取Api接口实例,解析注解生成request,线程切换
目录 一,Retrofit的基本使用 1.定义api接口 2.创建Retrofit实例 3.获取api接口实例发起请求 二,静态代理和动态代理 1,静态代理 2,动态代理 三,动态代理获取Api接口实例 四,解析接口方法注解&…...

范德蒙矩阵(Vandermonde 矩阵)简介:意义、用途及编程应用
参考: Introduction to Applied Linear Algebra – Vectors, Matrices, and Least Squares Stephen Boyd and Lieven Vandenberghe 书的网站: https://web.stanford.edu/~boyd/vmls/ Vandermonde 矩阵简介:意义、用途及编程应用 在数学和计算科学中&a…...

【中标麒麟服务器操作系统实例分享】java应用DNS解析异常分析及处理
了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer.kylinos.cn 文档中心:https://document.kylinos.cn 情况描述 中标麒麟服务器操作系统V7运行在 ARM…...

网安瞭望台第17期:Rockstar 2FA 故障催生 FlowerStorm 钓鱼即服务扩张现象剖析
国内外要闻 Rockstar 2FA 故障催生 FlowerStorm 钓鱼即服务扩张现象剖析 在网络安全的复杂战场中,近期出现了一个值得关注的动态:名为 Rockstar 2FA 的钓鱼即服务(PhaaS)工具包遭遇变故,意外推动了另一个新生服务 Flo…...

玩转OCR | 探索腾讯云智能结构化识别新境界
📝个人主页🌹:Eternity._ 🌹🌹期待您的关注 🌹🌹 ❀ 玩转OCR 腾讯云智能结构化识别产品介绍服务应用产品特征行业案例总结 腾讯云智能结构化识别 腾讯云智能结构化OCR产品分为基础版与高级版&am…...

idea2024创建JavaWeb项目以及配置Tomcat详解
今天呢,博主的学习进度也是步入了JavaWeb,目前正在逐步杨帆旗航,迎接全新的狂潮海浪。 那么接下来就给大家出一期有关JavaWeb的配置教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正…...

外连接转AntiJoin的应用场景与限制条件 | OceanBase SQL 查询改写系列
在《SQL 改写系列:外连接转内连接的常见场景与错误》一文中,我们了解到谓词条件可以过滤掉连接结果中的 null 情形的,将外连接转化为内连接的做法是可行的,正如图1中路径(a)所示。此时,敏锐的你或许会进一步思考&#…...

华为实训课笔记 2024 1223-1224
华为实训 12/2312/24 12/23 [Huawei]stp enable --开启STP display stp brief --查询STP MSTID Port Role STP State Protection 实例ID 端口 端口角色 端口状态 是否开启保护[Huawei]display stp vlan xxxx --查询制定vlan的生成树计算结…...

MySQL超详细安装配置教程(亲测有效)
目录 1.下载mysql 2.环境配置 3.安装mysql 4.navicat工具下载与连接 5总结 1.下载mysql mysql下载--MySQL :: 下载 MySQL 社区服务器 下载的时候这里直接逃过就行 我这里的版本是最新的mysql8.0.37 下载完成之后,将压缩包进行解压 这里我建议大…...