浅析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) 。 二叉树的 垂序遍历 从最左边的列开始直到…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...

【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...