浅析Linux追踪技术之ftrace:Tracepoint
文章目录
- 概述
- Tracepoint使用
- 定义Tracepoint
- 添加Tracepoint调用
- Tracepoint数据结构
- TRACE_EVENT实现
- DECLARE_TRACE
- __DECLARE_TRACE
- trace_xxx函数
- 相关参考
概述
Tracepoint(跟踪点)是添加到代码流程中的调用点,并且允许开发者注册自定义的回调函数执行。默认情况下,跟踪点是关闭的状态,不会对原代码逻辑造成影响;当跟踪点为开启状态时,每次运行到跟踪点,都会调用开发者注册的回调函数。
Tracepoint使用
开发者使用Tracepoint需要进行两个步骤:
- 定义Tracepoint;
- 在代码流程中添加对跟踪点的调用。
定义Tracepoint
Linux内核使用TRACE_EVENT宏来定义以及向系统中添加一个Tracepoint,使用方式如下:
TRACE_EVENT(block_rq_complete,TP_PROTO(struct request *rq, int error, unsigned int nr_bytes),TP_ARGS(rq, error, nr_bytes),TP_STRUCT__entry(__field( dev_t, dev )__field( sector_t, sector )__field( unsigned int, nr_sector )__field( int, error )__array( char, rwbs, RWBS_LEN )__dynamic_array( char, cmd, 1 )),TP_fast_assign(__entry->dev = rq->rq_disk ? disk_devt(rq->rq_disk) : 0;__entry->sector = blk_rq_pos(rq);__entry->nr_sector = nr_bytes >> 9;__entry->error = error;blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, nr_bytes);__get_str(cmd)[0] = '\0';),TP_printk("%d,%d %s (%s) %llu + %u [%d]",MAJOR(__entry->dev), MINOR(__entry->dev),__entry->rwbs, __get_str(cmd),(unsigned long long)__entry->sector,__entry->nr_sector, __entry->error)
);
其中:
- block_rq_complete为跟踪点名称;
- TP_PROTO部分定义了跟踪点回调函数原型;
- TP_ARGS部分定义了回调函数的参数;
- TP_STRUCT__entry部分定义了跟踪程序可以使用的数据结构,
- TP_fast_assign部分描述了传递数据的方式;
- TP_printk部分定义了打印数据结构的方法。
添加Tracepoint调用
bool blk_update_request(struct request *req, blk_status_t error,unsigned int nr_bytes)
{int total_bytes;trace_block_rq_complete(req, blk_status_to_errno(error), nr_bytes);if (!req->bio)return false;...
Tracepoint数据结构
Tracepoing机制的核心数据为tracepoint和tracepoint_func结构,tracepoint结构对应于一个跟踪点的概念,包含了跟踪点的名称、开关配置以及自定义的回调函数;而tracepoint_func结构描述了开发者注册的回调函数信息。

TRACE_EVENT实现
TRACE_EVENT宏定义如下:
#define TRACE_EVENT(name, proto, args, struct, assign, print) \DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))
- name:要创建的跟踪点的名称。
- prototype:跟踪点回调的原型
- args:与原型匹配的参数。
- struct:跟踪程序可以使用(但不需要)存储传递到跟踪点的数据的结构。
- assign:已类似于 C-like 的方式 将数据分配给结构。
- print:以可读的ASCII格式输出结构的方法。
DECLARE_TRACE
#define DECLARE_TRACE(name, proto, args) \__DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), \cpu_online(raw_smp_processor_id()), \PARAMS(void *__data, proto), \PARAMS(__data, args))
__DECLARE_TRACE
__DECLARE_TRACE宏定义了一系列内联函数(其中xxx为定义的tracepoint名称):
- trace_xxx:代码中调用trace_xxx函数记录tracepoint运行信息;
- register_trace_xxx:向tracepoint注册回调函数,在tracepoint使能时会调用;
- register_trace_prio_xxx:与register_trace_xxx相似,支持调用优先级;
- unregister_trace_xxx:向tracepoint去注册回调函数;
- trace_xxx_enabled:tracepoint使能接口
#define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \extern struct tracepoint __tracepoint_##name; \static inline void trace_##name(proto) // 定义trace_xxx函数,以上文示例即为trace_block_rq_complete \{ \if (static_key_false(&__tracepoint_##name.key)) \__DO_TRACE(&__tracepoint_##name, \TP_PROTO(data_proto), \TP_ARGS(data_args), \TP_CONDITION(cond), 0); \if (IS_ENABLED(CONFIG_LOCKDEP) && (cond)) { \WARN_ON_ONCE(!rcu_is_watching()); \} \} \__DECLARE_TRACE_RCU(name, PARAMS(proto), PARAMS(args), \PARAMS(cond), PARAMS(data_proto), PARAMS(data_args)) \static inline int \register_trace_##name(void (*probe)(data_proto), void *data) \ // 定义register_trace_xxx函数,以上文示例即为register_trace_rq_complete{ \return tracepoint_probe_register(&__tracepoint_##name, \(void *)probe, data); \} \static inline int \register_trace_prio_##name(void (*probe)(data_proto), void *data,\ // 定义register_trace_prio_xxx函数,以上文示例即为register_trace_prio_block_rq_completeint prio) \{ \return tracepoint_probe_register_prio(&__tracepoint_##name, \(void *)probe, data, prio); \} \static inline int \unregister_trace_##name(void (*probe)(data_proto), void *data) \ // 定义unregister_trace_xxx函数,以上文示例即为unregister_trace_prio_block_rq_complete{ \return tracepoint_probe_unregister(&__tracepoint_##name,\(void *)probe, data); \} \static inline void \check_trace_callback_type_##name(void (*cb)(data_proto)) \ // 定义check_trace_callback_type_xxx函数,以上文示例即为check_trace_callback_type_block_rq_complete{ \} \static inline bool \trace_##name##_enabled(void) \ // 定义trace_xxx_enabled函数,以上文示例即为trace_block_rq_complete_enabled { \return static_key_false(&__tracepoint_##name.key); \}
trace_xxx函数
trace_xxx函数内部主要是调用__DO_TRACE宏来完成实际的跟踪点信息处理,__DO_TRACE的核心流程是遍历tracepoint结构体里面的一个函数数组,执行对应的回调函数,这些回调函数由register_trace_xxx接口进行注册。
#define __DO_TRACE(tp, proto, args, cond, rcuidle) \do { \struct tracepoint_func *it_func_ptr; \void *it_func; \void *__data; \int __maybe_unused __idx = 0; \\if (!(cond)) \return; \\/* srcu can't be used from NMI */ \WARN_ON_ONCE(rcuidle && in_nmi()); \\/* keep srcu and sched-rcu usage consistent */ \preempt_disable_notrace(); \\/* \* For rcuidle callers, use srcu since sched-rcu \* doesn't work from the idle path. \*/ \if (rcuidle) { \__idx = srcu_read_lock_notrace(&tracepoint_srcu);\rcu_irq_enter_irqson(); \} \\it_func_ptr = rcu_dereference_raw((tp)->funcs); \\if (it_func_ptr) { \do { \it_func = (it_func_ptr)->func; \__data = (it_func_ptr)->data; \((void(*)(proto))(it_func))(args); \} while ((++it_func_ptr)->func); \} \\if (rcuidle) { \rcu_irq_exit_irqson(); \srcu_read_unlock_notrace(&tracepoint_srcu, __idx);\} \\preempt_enable_notrace(); \} while (0)
相关参考
- Linux tracepoint 简介
相关文章:
浅析Linux追踪技术之ftrace:Tracepoint
文章目录 概述Tracepoint使用定义Tracepoint添加Tracepoint调用 Tracepoint数据结构TRACE_EVENT实现DECLARE_TRACE__DECLARE_TRACE trace_xxx函数相关参考 概述 Tracepoint(跟踪点)是添加到代码流程中的调用点,并且允许开发者注册自定义的回…...
python ftp文件断点续传 并判断ftp文件下载完成
在Python中实现FTP文件的断点续传,通常涉及到以下步骤: 连接到FTP服务器。获取远程文件的大小。检查本地文件是否存在以及它的大小。如果本地文件不存在或大小小于远程文件,从上次中断的位置开始下载。下载完成后,检查文件大小以…...
SpringBoot+Vue3 完成小红书项目
简介 该项目采用微服务架构,实现了前后端分离的系统设计。在前端,我们选择了 Vue3 配合 TypeScript 和 ElementUi 框架,以提升开发效率和用户体验。而在后端,则是运用 SpringBoot 和 Mybatis-plus 进行开发,保证了系统…...
springboot集成Sa-Token及Redis的redisson客户端
文章目录 什么是Sa-Token?为什么集成Redis的redisson客户端?如何集成?maven依赖application.yml配置过滤器配置验证参考什么是Sa-Token? Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权…...
SQL世界之命令语句Ⅴ
目录 一、SQL CREATE INDEX 语句 1.SQL CREATE INDEX 语句 2.SQL CREATE INDEX 语法 3.SQL CREATE UNIQUE INDEX 语法 4.SQL CREATE INDEX 实例 二、SQL 撤销索引、表以及数据库 1.SQL DROP INDEX 语句 2.SQL DROP TABLE 语句 3.SQL DROP DATABASE 语句 4.SQL TRUNCA…...
Springboot拦截器中跨域失效的问题、同一个接口传入参数不同,一个成功,一个有跨域问题、拦截器和@CrossOrigin和@Controller
Springboot拦截器中跨域失效的问题 一、概述 1、具体场景 起因: 同一个接口,传入不同参数进行值的修改时,一个成功,另一个竟然失败,而且是跨域问题拦截器内的request参数调用getHeader方法时,获取不到前端…...
WordPress如何自建txt文本经典语录并随机显示一句话经典语录?
前面跟大家分享的『WordPress集成一言(Hitokoto)API经典语句功能』一文中就提供有自创API,其中懿古今顶部左上角显示的经典语录用的就是自建一个txt文本文件,然后再在前端网页指定位置随机显示语录。具体操作方法如下:…...
Java中JVM常用参数配置(提供配置示例)
目录 前言一、内存参数配置二、垃圾收集器配置三、GC策略配置3.1、基础通用配置3.2、Parallel 和 Parallel Old 常用参数配置3.3、CMS 常用参数配置3.4、G1 常用参数配置 四、GC日志配置五、dump 日志参数配置5.1、OutOfMemory异常时生成dump文件5.2、发生Full GC时生成dump文件…...
图论与图数据应用综述:从基础概念到知识图谱与图智能
目录 前言1 图论基础概念1.1 节点度1.2 度分布1.3 邻接矩阵 2 探索图的高级概念2.1 最短路径的关键性2.2 图的直径与平均路径的意义2.3 循环与路径类型的多样性 3 深入探讨图的广泛应用领域3.1 知识图谱的知识管理3.2 图智能在复杂决策中的应用3.3 图数据挖掘与分析的多领域应用…...
知识碎片-SpringBoot统一返回结果和捕获异常
统一返回结果 定义统一返回结果类ResultResponse定义新注解ResponseResult来标记需要拦截的方法或类添加RestControllerAdvice注解,实现ResponseBodyAdvice接口,重写support, beforeBodyWrite方法 统一结果类ResultResponse Setter Getter public cla…...
Open-FWI代码解析(1)
目录 1. dataset文件 1.1初始化网络 1.2load_every函数 1.3 getitem函数 1.4测试函数 2. transforms文件 2.1裁切函数和翻转函数 2.2上\下采样函数 2.3加入随机因子的上\下采样函数 2.4填充函数 2.5标准图像函数 2.6标准化函数 2.7归一化函数 2.8反归一化 2.9添加噪声的函数 …...
移动机器人激光SLAM导航(五):Cartographer SLAM 篇
参考 Cartographer 官方文档Cartographer 从入门到精通 1. Cartographer 安装 1.1 前置条件 推荐在刚装好的 Ubuntu 16.04 或 Ubuntu 18.04 上进行编译ROS 安装:ROS学习1:ROS概述与环境搭建 1.2 依赖库安装 资源下载完解压并执行以下指令 https://pa…...
第四篇【传奇开心果微博系列】Python微项目技术点案例示例:美女颜值判官
传奇开心果微博系列 系列微博目录Python微项目技术点案例示例系列 微博目录一、微项目目标二、雏形示例代码三、扩展思路四、添加不同类型的美女示例代码五、增加难度等级示例代码六、添加特殊道具示例代码七、设计关卡系统示例代码八、添加音效和背景音乐示例代码九、多人游戏…...
Python学习之路-初识爬虫:requests
Python学习之路-初识爬虫:requests requests的作用 作用:发送网络请求,返回响应数据 中文文档 : http://docs.python-requests.org/zh_CN/latest/index.html 为什么学requests而不是urllib requests的底层实现就是urllibrequests在pytho…...
Linux 常用的命令
① 基本命令 uname -m 显示机器的处理器架构uname -r 显示正在使用的内核版本dmidecode -q 显示硬件系统部件(SMBIOS / DMI) hdparm -i /dev/hda 罗列一个磁盘的架构特性hdparm -tT /dev/sda 在磁盘上执行测试性读取操作系统信息arch 显示机器的处理器架构uname -m 显示机器的处…...
假期作业 10
1.整理磁盘操作的完整流程,如何接入虚拟机,是否成功识别,对磁盘分区工具的使用,格式化,挂载以及取消挂载 U盘接入虚拟机 在虚拟机--->可移动设备--->找到U盘---->连接 检测U盘是否被虚拟机识别 ls /dev/s…...
【洛谷 P3367】【模板】并查集 题解(并查集+路径压缩)
【模板】并查集 题目描述 如题,现在有一个并查集,你需要完成合并和查询操作。 输入格式 第一行包含两个整数 N , M N,M N,M ,表示共有 N N N 个元素和 M M M 个操作。 接下来 M M M 行,每行包含三个整数 Z i , X i , Y i Z_i,X_i,Y…...
Netty应用(一) 之 NIO概念 基本编程
目录 第一章 概念引入 1.分布式概念引入 第二章 Netty基础 - NIO 1.引言 1.1 什么是Netty? 1.2 为什么要学习Netty? 2.NIO编程 2.1 传统网络通信中开发方式及问题(BIO) 2.1.1 多线程版网络编程 2.1.2 线程池版的网络编程…...
tkinter-TinUI-xml实战(10)展示画廊
tkinter-TinUI-xml实战(10)展示画廊 引言声明文件结构核心代码主界面统一展示控件控件展示界面单一展示已有展示多类展示 最终效果在这里插入图片描述  ………… 结语 引言…...
LeetCode二叉树的垂序遍历
题目描述 给你二叉树的根结点 root ,请你设计算法计算二叉树的 垂序遍历 序列。 对位于 (row, col) 的每个结点而言,其左右子结点分别位于 (row 1, col - 1) 和 (row 1, col 1) 。树的根结点位于 (0, 0) 。 二叉树的 垂序遍历 从最左边的列开始直到…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...
企业大模型服务合规指南:深度解析备案与登记制度
伴随AI技术的爆炸式发展,尤其是大模型(LLM)在各行各业的深度应用和整合,企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者,还是积极拥抱AI转型的传统企业,在面向公众…...
