蚊章汇 - 跟踪
type: channel
link: https://linuxcn.bwsl.wang/tag/%E8%B7%9F%E8%B8%AA/
items: 硬核观察 #736 研究发现所有的网络拥堵算法都解决不了“饿死”问题
items: 你安装的 Chrome 扩展的组合可以跟踪你
items: 使用 Grafana Tempo 进行分布式跟踪
items: 分布式跟踪系统的四大功能模块如何协同工作
items: Google Analytics 的一些用法介绍
items: 使用 Ptrace 去拦截和仿真 Linux 系统调用
items: 使用 ftrace 跟踪内核
items: ftrace：跟踪你的内核函数！
items: Linux 中的 DTrace ：BPF 进入 4.9 内核
items: 使用 Linux 的 strace 命令跟踪/调试程序的常用选项

硬核观察 #736 研究发现所有的网络拥堵算法都解决不了“饿死”问题
type: item
date: 2022-08-23T02:41:00+08:00
description: 研究发现所有的网络拥塞控制算法都可能是非常不公平的尽管在过去大约 40 年中提出了数百种控制计算机网络“拥堵”延迟的关键算法，但没有明显的赢家。一项新的研究发现，每种拥塞控制算法都无法解决“饿死”的问题，即让一些用户占据了所有的带宽，而至少有一个人基本上得不到带宽。拥塞控制算法依靠数据包的丢失和延迟作为细节来推断拥塞，并决定发送数据的速度。然而，数据包可能因为网络拥堵以外的原因而丢失和延迟 —— 这被称之为网络“抖动”。而拥塞控制算法无法区分由拥塞和抖动造成的延迟的区别，由抖动引起的延迟是不可预测的，最终会导致出现饥饿的情况。消息来源：Slashdot老王点评：这就是算法的不公平，或许，限定在算法的层面上，并无一个完美的解决方案。TikTok 否认内置浏览器记录用户输入研究发现，流行 iOS 应用如 TikTok、Instagram、FB Messenger 和 Facebook 都支持用户在应用内打开浏览器访问第三方网站，期间会植入跟踪代码。以 TikTok 为例，它会记录用户的所有键盘输入，包括密码信用卡信息等敏感数据，以及屏幕上的每一次点击。从技术上说这相当于安装了一个键盘记录器。在这一报道发表之后，TikTok 发表声明，证实该功能存在，但 TikTok 并没有利用这些代码。TikTok 表示应用内浏览器旨在提供更好的用户体验，它植入第三方网站的 JS 代码是为了调试、排错和性能监视。消息来源：Solidot老王点评：植入这种第三方 SDK，即便是没启用，但是谁知道你什么时候会启用呢？美国绝大部分雇主正在跟踪员工的生产力根据《纽约时报》的调查，美国 10 个最大的私人雇主中，有 8 个正在为他们的雇员追踪生产力指标。其中一些软件测量活动时间，观察键盘停顿，甚至默默地计算击键次数。他们看到了从写电子邮件的时间到键盘活动的一切。如果员工没有达到预期的目标，就会产生影响：一个催促的通知，一个跳过的奖金，或者一个在家工作的日子被剥夺。对于在返回办公室的斗争中投降的雇主来说，这种监控是保持控制感的一种方式。消息来源：Slashdot老王点评：这可真是“工具人”，我觉得这和用代码行数来统计程序员的绩效具有“异曲同工之妙”。

你安装的 Chrome 扩展的组合可以跟踪你
type: item
date: 2022-06-28T21:12:31+08:00
description: 这会成为放弃基于 Chromium 的浏览器并开始使用 Firefox 的一个理由吗？也许吧，决定权在你。即使你有了所有的隐私扩展和各种保护功能，别人仍然有方法可以识别你或跟踪你。请注意，并非所有浏览器都是如此，本文中，我们主要关注基于 Chromium 的浏览器，并将谷歌 Chrome 作为“主要嫌疑人”。以前，在 Chromium 浏览器上，尽管别人已经能够检测到你已安装的扩展程序，但许多扩展程序都实施了某些保护措施来防止这种检测。然而，一位名为 “z0ccc” 的安全研究人员发现了一种检测已安装 Chrome 浏览器扩展程序的新方法，该方法可进一步用于通过“浏览器指纹识别”来跟踪你。如果你还不知道的话： 浏览器指纹识别 Browser Fingerprinting 是指收集有关你的设备/浏览器的各种信息，以创建唯一的指纹 ID（哈希），从而在互联网上识别你的一种跟踪方法。“各种信息”包括：浏览器名称、版本、操作系统、已安装的扩展程序、屏幕分辨率和类似的技术数据。这听起来像是一种无害的数据收集技术，但可以使用这种跟踪方法在线跟踪你。检测谷歌 Chrome 扩展研究人员发布了一个开源项目 “Extension Fingerprints”，你可以使用它来测试你安装的 Chrome 扩展是否能被检测到。新技术涉及一种“时间差”方法，该工具比较了扩展程序获取资源的时间。与浏览器上未安装的其他扩展相比，受保护的扩展需要更多时间来获取资源。因此，这有助于从 1000 多个扩展列表中识别出一些扩展。关键是：即使有了各种新的进步和技术来防止跟踪，Chrome 网上应用店的扩展也可以被检测到。并且，在检测到已安装的扩展程序后，别人可以就使用浏览器指纹识别，对你进行在线跟踪。令人惊讶的是，即使你安装有 uBlocker、AdBlocker、或 Privacy Badger（一些流行的以隐私为重点的扩展程序）之类的扩展程序，使用了这种方法，它们也都可以被检测到。你可以在它的 GitHub 页面 上查看所有技术细节。如果你想自己测试它，请前往它的 扩展指纹识别网站 自行检查。拯救 Firefox？嗯，似乎是的，毕竟我出于各种原因，不断回到 Firefox。这个新发现的（跟踪）方法应该适用于所有基于 Chromium 的浏览器。我在 Brave 和谷歌 Chrome 上都测试了这个方法。研究人员还提到，该工具不能在使用微软应用商店中的扩展的微软 Edge 上工作。但是，相同的跟踪方法仍然有效。正如研究人员指出，Mozilla Firefox 可以避免这种情况，因为每个浏览器实例的扩展 ID 都是唯一的。via: https://news.itsfoss.com/chrome-extension-tracking/作者：Ankush Das 选题：lkxed 译者：lkxed 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出

使用 Grafana Tempo 进行分布式跟踪
type: item
date: 2021-03-24T06:14:03+08:00
description: Grafana Tempo 是一个新的开源、大容量分布式跟踪后端。Grafana 的 Tempo 是出自 Grafana 实验室的一个简单易用、大规模的、分布式的跟踪后端。Tempo 集成了 Grafana、Prometheus 以及 Loki，并且它只需要对象存储进行操作，因此成本低廉，操作简单。我从一开始就参与了这个开源项目，所以我将介绍一些关于 Tempo 的基础知识，并说明为什么云原生社区会注意到它。分布式跟踪想要收集对应用程序请求的遥测数据是很常见的。但是在现在的服务器中，单个应用通常被分割为多个微服务，可能运行在几个不同的节点上。分布式跟踪是一种获得关于应用的性能细粒度信息的方式，该应用程序可能由离散的服务组成。当请求到达一个应用时，它提供了该请求的生命周期的统一视图。Tempo 的分布式跟踪可以用于单体应用或微服务应用，它提供 请求范围的信息，使其成为可观察性的第三个支柱（另外两个是度量和日志）。接下来是一个分布式跟踪系统生成应用程序甘特图的示例。它使用 Jaeger HotROD 的演示应用生成跟踪，并把它们存到 Grafana 云托管的 Tempo 上。这个图展示了按照服务和功能划分的请求处理时间。减少索引的大小在丰富且定义良好的数据模型中，跟踪包含大量信息。通常，跟踪后端有两种交互：使用元数据选择器（如服务名或者持续时间）筛选跟踪，以及筛选后的可视化跟踪。为了加强搜索，大多数的开源分布式跟踪框架会对跟踪中的许多字段进行索引，包括服务名称、操作名称、标记和持续时间。这会导致索引很大，并迫使你使用 Elasticsearch 或者 Cassandra 这样的数据库。但是，这些很难管理，而且大规模运营成本很高，所以我在 Grafana 实验室的团队开始提出一个更好的解决方案。在 Grafana 中，我们的待命调试工作流从使用指标报表开始（我们使用 Cortex 来存储我们应用中的指标，它是一个云原生基金会孵化的项目，用于扩展 Prometheus），深入研究这个问题，筛选有问题服务的日志（我们将日志存储在 Loki 中，它就像 Prometheus 一样，只不过 Loki 是存日志的），然后查看跟踪给定的请求。我们意识到，我们过滤时所需的所有索引信息都可以在 Cortex 和 Loki 中找到。但是，我们需要一个强大的集成，以通过这些工具实现跟踪的可发现性，并需要一个很赞的存储，以根据跟踪 ID 进行键值查找。这就是 Grafana Tempo 项目的开始。通过专注于给定检索跟踪 ID 的跟踪，我们将 Tempo 设计为最小依赖性、大容量、低成本的分布式跟踪后端。操作简单，性价比高Tempo 使用对象存储后端，这是它唯一的依赖。它既可以被用于单一的二进制下，也可以用于微服务模式（请参考仓库中的 例子，了解如何轻松上手）。使用对象存储还意味着你可以存储大量的应用程序的痕迹，而无需任何采样。这可以确保你永远不会丢弃那百万分之一的出错或具有较高延迟的请求的跟踪。与开源工具的强大集成Grafana 7.3 包括了 Tempo 数据源，这意味着你可以在 Grafana UI 中可视化来自Tempo 的跟踪。而且，Loki 2.0 的新查询特性 使得 Tempo 中的跟踪更简单。为了与 Prometheus 集成，该团队正在添加对 范例 exemplar 的支持，范例是可以添加到时间序列数据中的高基数元数据信息。度量存储后端不会对它们建立索引，但是你可以在 Grafana UI 中检索和显示度量值。尽管范例可以存储各种元数据，但是在这个用例中，存储跟踪 ID 是为了与 Tempo 紧密集成。这个例子展示了使用带有请求延迟直方图的范例，其中每个范例数据点都链接到 Tempo 中的一个跟踪。元数据一致性作为容器化应用程序运行的应用发出的遥测数据通常具有一些相关的元数据。这可以包括集群 ID、命名空间、吊舱 IP 等。这对于提供基于需求的信息是好的，但如果你能将元数据中包含的信息用于生产性的东西，那就更好了。 例如，你可以使用 Grafana 云代理将跟踪信息导入 Tempo 中，代理利用 Prometheus 服务发现机制轮询 Kubernetes API 以获取元数据信息，并且将这些标记添加到应用程序发出的跨域数据中。由于这些元数据也在 Loki 中也建立了索引，所以通过元数据转换为 Loki 标签选择器，可以很容易地从跟踪跳转到查看给定服务的日志。下面是一个一致元数据的示例，它可用于Tempo跟踪中查看给定范围的日志。云原生Grafana Tempo 可以作为容器化应用，你可以在如 Kubernetes、Mesos 等编排引擎上运行它。根据获取/查询路径上的工作负载，各种服务可以水平伸缩。你还可以使用云原生的对象存储，如谷歌…

分布式跟踪系统的四大功能模块如何协同工作
type: item
date: 2020-02-03T08:44:37+08:00
description: 了解分布式跟踪中的主要体系结构决策，以及各部分如何组合在一起。早在十年前，认真研究过分布式跟踪基本上只有学者和一小部分大型互联网公司中的人。对于任何采用微服务的组织来说，它如今成为一种筹码。其理由是确立的：微服务通常会发生让人意想不到的错误，而分布式跟踪则是描述和诊断那些错误的最好方法。也就是说，一旦你准备将分布式跟踪集成到你自己的应用程序中，你将很快意识到对于不同的人来说“ 分布式跟踪 Distributed Tracing ”一词意味着不同的事物。此外，跟踪生态系统里挤满了具有相似内容的重叠项目。本文介绍了分布式跟踪系统中四个（可能）独立的功能模块，并描述了它们间将如何协同工作。分布式跟踪：一种思维模型大多数用于跟踪的思维模型来源于 Google 的 Dapper 论文。OpenTracing 使用相似的术语，因此，我们从该项目借用了以下术语： 跟踪 Trace ：事物在分布式系统运行的过程描述。 跨度 Span ：一种命名的定时操作，表示工作流的一部分。跨度可接受键值对标签以及附加到特定跨度实例的细粒度的、带有时间戳的结构化日志。 跨度上下文 Span context ：携带分布式事务的跟踪信息，包括当它通过网络或消息总线将服务传递给服务时。跨度上下文包含跟踪标识符、跨度标识符以及跟踪系统所需传播到下游服务的任何其他数据。如果你想要深入研究这种思维模式的细节，请仔细参照 OpenTracing 技术规范。四大功能模块从应用层分布式跟踪系统的观点来看，现代软件系统架构如下图所示：现代软件系统的组件可分为三类：应用程序和业务逻辑：你的代码。广泛共享库：他人的代码广泛共享服务：他人的基础架构这三类组件有着不同的需求，驱动着监控应用程序的分布式跟踪系统的设计。最终的设计得到了四个重要的部分： 跟踪检测 API A tracing instrumentation API ：修饰应用程序代码 线路协议 Wire protocol ：在 RPC 请求中与应用程序数据一同发送的规定 数据协议 Data protocol ：将异步信息（带外）发送到你的分析系统的规定 分析系统 Analysis system ：用于处理跟踪数据的数据库和交互式用户界面为了更深入的解释这个概念，我们将深入研究驱动该设计的细节。如果你只需要我的一些建议，请跳转至下方的四大解决方案。需求，细节和解释应用程序代码、共享库以及共享式服务在操作上有显著的差别，这种差别严重影响了对其进行检测的请求操作。检测应用程序代码和业务逻辑在任何特定的微服务中，由微服务开发者编写的大部分代码是应用程序或者商业逻辑。这部分代码规定了特定区域的操作。通常，它包含任何特殊、独一无二的逻辑判断，这些逻辑判断首先证明了创建新型微服务的合理性。基本上按照定义，该代码通常不会在多个服务中共享或者以其他方式出现。也即是说你仍需了解它，这也意味着需要以某种方式对它进行检测。一些监控和跟踪分析系统使用 黑盒代理 black-box agents 自动检测代码，另一些系统更想使用显式的白盒检测工具。对于后者，抽象跟踪 API 提供了许多对于微服务的应用程序代码来说更为实用的优势：抽象 API 允许你在不重新编写检测代码的条件下换新的监视工具。你可能想要变更云服务提供商、供应商和监测技术，而一大堆不可移植的检测代码将会为该过程增加有意义的开销和麻烦。事实证明，除了生产监控之外，该工具还有其他有趣的用途。现有的项目使用相同的跟踪工具来驱动测试工具、分布式调试器、“混沌工程”故障注入器和其他元应用程序。但更重要的是，若将应用程序组件提取到共享库中要怎么办呢？由上述内容可得到结论：检测共享库在大多数应用程序中出现的实用程序代码（处理网络请求、数据库调用、磁盘写操作、线程、并发管理等）通常情况下是通用的，而非特别应用于某个特定应用程序。这些代码会被打包成库和框架，而后就可以被装载到许多的微服务上并且被部署到多种不同的环境中。其真正的不同是：对于共享代码，其他人则成为了使用者。大多数用户有不同的依赖关系和操作风格。如果尝试去使用该共享代码，你将会注意到几个常见的问题：你需要一个 API 来编写检测。然而，你的库并不知道你正在使用哪个分析系统。会有多种选择，并且运行在相同应用下的所有库无法做出不兼容的选择。由于这些包封装了所有网络处理代码，因此从请求报头注入和提取跨度上下文的任务往往指向 RPC 库。然而，共享库必须了解到每个应用程序正在使用哪种跟踪协议。最后，你不想强制用户使用相互冲突的依赖项。大多数用户有不同的依赖关系和操作风格。即使他们使用 gRPC，绑定的 gRPC 版本是否相同？因此任何你的库附带用于跟踪的监控 API 必定是免于依赖的。因此，一个（a）没有依赖关系、（b）与线路协议无关、（c）使用流行的供…

Google Analytics 的一些用法介绍
type: item
date: 2019-10-15T01:49:51+08:00
description: Google Analytics （GA）这个最流行的用户活动追踪工具我们或多或少都听说过甚至使用过，但它的用途并不仅仅限于对页面访问的追踪。作为一个既实用又流行的工具，它已经受到了广泛的欢迎，因此我们将要在下文中介绍如何在各种 Angular 和 React 单页应用中使用 Google Analytics。这篇文章源自这样一个问题：如何对单页应用中的页面访问进行跟踪？通常来说，有很多的方法可以解决这个问题，在这里我们只讨论其中的一种方法。下面我会使用 Angular 来写出对应的实现，如果你使用的是 React，相关的用法和概念也不会有太大的差别。接下来就开始吧。准备好应用程序首先需要有一个 追踪 ID tracking ID 。在开始编写业务代码之前，要先准备好一个追踪 ID，通过这个唯一的标识，Google Analytics 才能识别出某个点击或者某个页面访问是来自于哪一个应用。按照以下的步骤：访问 https://analytics.google.com；提交指定信息以完成注册，并确保可用于 Web 应用，因为我们要开发的正是一个 Web 应用；同意相关的条款，生成一个追踪 ID；保存好追踪 ID。追踪 ID 拿到了，就可以开始编写业务代码了。添加 analytics.js 脚本Google 已经帮我们做好了接入之前需要做的所有事情，接下来就是我们的工作了。不过我们要做的也很简单，只需要把下面这段脚本添加到应用的 index.html 里，就可以了： 现在我们来看一下 Google Analytics 是如何在应用程序中初始化的。创建追踪器首先创建一个应用程序的追踪器。在 app.component.ts 中执行以下两个步骤：声明一个名为 ga，类型为 any 的全局变量（在 Typescript 中需要制定变量类型）；将下面一行代码加入到 ngInInit() 中。ga('create', <你的追踪 ID>, 'auto');这样就已经成功地在应用程序中初始化了一个 Google Analytics 的追踪器了。由于追踪器的初始化是在 OnInit() 函数中执行的，因此每当应用程序启动，追踪器就会启动。在单页应用中记录页面访问情况我们需要实现的是记录 访问路由 route-visits 。如何记录用户在一个应用中不同部分的访问，这是一个难点。从功能上来看，单页应用中的路由对应了传统多页面应用中各个页面之间的跳转，因此我们需要记录访问路由。要做到这一点尽管不算简单，但仍然是可以实现的。在 app.component.ts 的 ngOnInit() 函数中添加以下的代码片段：import { Router, NavigationEnd } from '@angular/router'; ... constructor(public router: Router) {} ... this.router.events.subscribe( event => { if (event instanceof NavigationEnd) { ga('set', 'page', event.urlAfterRedirects); ga('send', { hitType: 'pageview', hitCallback: () => { this.pageViewSent = true; }}); } } );神奇的是，只需要这么几行代码，就实现了 Angular 应用中记录页面访问情况的功能。这段代码实际上做了以下几件事情：从 Angular Router 中导入了 Router、NavigationEnd；通过构造函数中将 Router 添加到组件中；然后订阅 router 事件，也就是由 Angular Router 发出的所有事件；只要产生了一个 NavigationEnd 事件实例，就将路由和目标作为一个页面访问进行记录。这样，只要使用到了页面路由，就会向 Google Analytics 发送一条页面访问记录，在 Google Analytics 的在线控制台中可以看到这些记录。类似地，我们可以用相同的方式来记录除了页面访问之外的活动，例如某个界面的查看次数或者时长等等。只要像上面的代码那样使用 hitCallBack() 就可以在有需要收集的数据的时候让应用程序作出反应，这里我们做的事情仅仅是把一个变量的值设为 true，但实际上 hitCallBack() 中可以执行任何代码。追踪用户交互活动除了页面访问记录之外，Google Analytics 还经常被用于追踪用户的交互活动，例如某个按钮的点击情况。“提交按钮被用户点击了多少次？”，“产品手册会被经常查阅吗？”这些都是 Web 应用程序的产品评审会议上的常…

使用 Ptrace 去拦截和仿真 Linux 系统调用
type: item
date: 2018-08-22T21:38:00+08:00
description: ptrace(2)（“ 进程跟踪 process trace ”）系统调用通常都与调试有关。它是类 Unix 系统上通过原生调试器监测被调试进程的主要机制。它也是实现 strace（ 系统调用跟踪 system call trace ）的常见方法。使用 Ptrace，跟踪器可以暂停被跟踪进程，检查和设置寄存器和内存，监视系统调用，甚至可以 拦截 （ intercepting ） 系统调用。通过拦截功能，意味着跟踪器可以篡改系统调用参数，篡改系统调用的返回值，甚至阻塞某些系统调用。言外之意就是，一个跟踪器本身完全可以提供系统调用服务。这是件非常有趣的事，因为这意味着一个跟踪器可以仿真一个完整的外部操作系统，而这些都是在没有得到内核任何帮助的情况下由 Ptrace 实现的。问题是，在同一时间一个进程只能被一个跟踪器附着，因此在那个进程的调试期间，不可能再使用诸如 GDB 这样的工具去仿真一个外部操作系统。另外的问题是，仿真系统调用的开销非常高。在本文中，我们将专注于 x86-64 Linux 的 Ptrace，并将使用一些 Linux 专用的扩展。同时，在本文中，我们将忽略掉一些错误检查，但是完整的源代码仍然会包含这些错误检查。本文中的可直接运行的示例代码在这里：https://github.com/skeeto/ptrace-examplesstrace在进入到最有趣的部分之前，我们先从回顾 strace 的基本实现来开始。它不是 DTrace，但 strace 仍然非常有用。Ptrace 一直没有被标准化。它的接口在不同的操作系统上非常类似，尤其是在核心功能方面，但是在不同的系统之间仍然存在细微的差别。ptrace(2) 的原型基本上应该像下面这样，但特定的类型可能有些差别。long ptrace(int request, pid_t pid, void *addr, void *data);pid 是被跟踪进程的 ID。虽然同一个时间只有一个跟踪器可以附着到该进程上，但是一个跟踪器可以附着跟踪多个进程。request 字段选择一个具体的 Ptrace 函数，比如 ioctl(2) 接口。对于 strace，只需要两个：PTRACE_TRACEME：这个进程被它的父进程跟踪。PTRACE_SYSCALL：继续跟踪，但是在下一下系统调用入口或出口时停止。PTRACE_GETREGS：取得被跟踪进程的寄存器内容副本。另外两个字段，addr 和 data，作为所选的 Ptrace 函数的一般参数。一般情况下，可以忽略一个或全部忽略，在那种情况下，传递零个参数。strace 接口实质上是前缀到另一个命令之前。$ strace [strace options] program [arguments]最小化的 strace 不需要任何选项，因此需要做的第一件事情是 —— 假设它至少有一个参数 —— 在 argv 尾部的 fork(2) 和 exec(2) 被跟踪进程。但是在加载目标程序之前，新的进程将告知内核，目标程序将被它的父进程继续跟踪。被跟踪进程将被这个 Ptrace 系统调用暂停。pid_t pid = fork(); switch (pid) { case -1: /* error */ FATAL("%s", strerror(errno)); case 0: /* child */ ptrace(PTRACE_TRACEME, 0, 0, 0); execvp(argv[1], argv + 1); FATAL("%s", strerror(errno)); }父进程使用 wait(2) 等待子进程的 PTRACE_TRACEME，当 wait(2) 返回后，子进程将被暂停。waitpid(pid, 0, 0);在允许子进程继续运行之前，我们告诉操作系统，被跟踪进程和它的父进程应该一同被终止。一个真实的 strace 实现可能会设置其它的选择，比如： PTRACE_O_TRACEFORK。ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL);剩余部分就是一个简单的、无休止的循环了，每循环一次捕获一个系统调用。循环体总共有四步：等待进程进入下一个系统调用。输出系统调用的一个描述。允许系统调用去运行并等待返回。输出系统调用返回值。这个 PTRACE_SYSCALL 请求被用于等待下一个系统调用时开始，和等待那个系统调用退出。和前面一样，需要一个 wait(2) 去等待被跟踪进程进入期望的状态。ptrace(PTRACE_SYSCALL, pid, 0, 0); waitpid(pid, 0, 0);当 wait(2) 返回时，进行了系统调用的线程的寄存器中写入了该系统调用的系统…

使用 ftrace 跟踪内核
type: item
date: 2018-07-15T20:17:20+08:00
description: 在内核层面上分析事件有很多的工具：SystemTap、ktap、Sysdig、LTTNG 等等，你也可以在网络上找到关于这些工具的大量介绍文章和资料。而对于使用 Linux 原生机制去跟踪系统事件以及检索/分析故障信息的方面的资料却很少找的到。这就是 ftrace，它是添加到内核中的第一款跟踪工具，今天我们来看一下它都能做什么，让我们从它的一些重要术语开始吧。内核跟踪和分析 内核分析 Kernel profiling 可以发现性能“瓶颈”。分析能够帮我们发现在一个程序中性能损失的准确位置。特定的程序生成一个 概述 profile — 这是一个事件总结 — 它能够用于帮我们找出哪个函数占用了大量的运行时间。尽管这些程序并不能识别出为什么会损失性能。瓶颈经常发生在无法通过分析来识别的情况下。要推断出为什么会发生事件，就必须保存发生事件时的相关上下文，这就需要去 跟踪 tracing 。跟踪可以理解为在一个正常工作的系统上活动的信息收集过程。它使用特定的工具来完成这项工作，就像录音机来记录声音一样，用它来记录各种系统事件。跟踪程序能够同时跟踪应用级和操作系统级的事件。它们收集的信息能够用于诊断多种系统问题。有时候会将跟踪与日志比较。它们两者确时很相似，但是也有不同的地方。对于跟踪，记录的信息都是些低级别事件。它们的数量是成百上千的，甚至是成千上万的。对于日志，记录的信息都是些高级别事件，数量上通常少多了。这些包含用户登录系统、应用程序错误、数据库事务等等。就像日志一样，跟踪数据可以被原样读取，但是用特定的应用程序提取的信息更有用。所有的跟踪程序都能这样做。在内核跟踪和分析方面，Linux 内核有三个主要的机制： 跟踪点 tracepoint ：一种基于静态测试代码的工作机制 探针 kprobe ：一种动态跟踪机制，用于在任意时刻中断内核代码的运行，调用它自己的处理程序，在完成需要的操作之后再返回perf\_events —— 一个访问 PMU（ 性能监视单元 Performance Monitoring Unit ）的接口我并不想在这里写关于这些机制方面的内容，任何对它们感兴趣的人可以去访问 Brendan Gregg 的博客。使用 ftrace，我们可以与这些机制进行交互，并可以从用户空间直接得到调试信息。下面我们将讨论这方面的详细内容。示例中的所有命令行都是在内核版本为 3.13.0-24 的 Ubuntu 14.04 中运行的。ftrace：常用信息ftrace 是 Function Trace 的简写，但它能做的远不止这些：它可以跟踪上下文切换、测量进程阻塞时间、计算高优先级任务的活动时间等等。ftrace 是由 Steven Rostedt 开发的，从 2008 年发布的内核 2.6.27 中开始就内置了。这是为记录数据提供的一个调试 Ring 缓冲区的框架。这些数据由集成到内核中的跟踪程序来采集。ftrace 工作在 debugfs 文件系统上，在大多数现代 Linux 发行版中都默认挂载了。要开始使用 ftrace，你将进入到 sys/kernel/debug/tracing 目录（仅对 root 用户可用）：# cd /sys/kernel/debug/tracing 这个目录的内容看起来应该像这样：аvailable_filter_functions options stack_trace_filter available_tracers per_cpu trace buffer_size_kb printk_formats trace_clock buffer_total_size_kb README trace_marker current_tracer saved_cmdlines trace_options dyn_ftrace_total_info set_event trace_pipe enabled_functions set_ftrace_filter trace_stat events set_ftrace_notrace tracing_cpumask free_buffer set_ftrace_pid tracing_max_latency function_profile_enabled set_graph_function tracing_on instances set_graph_notrace tracing_thresh kprobe_events snapshot uprobe_events kprobe_profile stack_max_size uprobe_profile 我不想去描述这些文件和子目录；它们的描述在 官方文档 中已经写的很详细了。我只想去详细介绍与我们…

ftrace：跟踪你的内核函数！
type: item
date: 2018-01-24T19:46:58+08:00
description: 大家好！今天我们将去讨论一个调试工具：ftrace，之前我的博客上还没有讨论过它。还有什么能比一个新的调试工具更让人激动呢？这个非常棒的 ftrace 并不是个新的工具！它大约在 Linux 的 2.6 内核版本中就有了，时间大约是在 2008 年。这一篇是我用谷歌能找到的最早的文档。因此，如果你是一个调试系统的“老手”，可能早就已经使用它了！我知道，ftrace 已经存在了大约 2.5 年了（LCTT 译注：距本文初次写作时），但是还没有真正的去学习它。假设我明天要召开一个专题研究会，那么，关于 ftrace 应该讨论些什么？因此，今天是时间去讨论一下它了！什么是 ftrace？ftrace 是一个 Linux 内核特性，它可以让你去跟踪 Linux 内核的函数调用。为什么要这么做呢？好吧，假设你调试一个奇怪的问题，而你已经得到了你的内核版本中这个问题在源代码中的开始的位置，而你想知道这里到底发生了什么？每次在调试的时候，我并不会经常去读内核源代码，但是，极个别的情况下会去读它！例如，本周在工作中，我有一个程序在内核中卡死了。查看到底是调用了什么函数，能够帮我更好的理解在内核中发生了什么，哪些系统涉及其中！（在我的那个案例中，它是虚拟内存系统）。我认为 ftrace 是一个十分好用的工具（它肯定没有 strace 那样使用广泛，也比它难以使用），但是它还是值得你去学习。因此，让我们开始吧！使用 ftrace 的第一步不像 strace 和 perf，ftrace 并不是真正的 程序 – 你不能只运行 ftrace my_cool_function。那样太容易了！如果你去读 使用 ftrace 调试内核，它会告诉你从 cd /sys/kernel/debug/tracing 开始，然后做很多文件系统的操作。对于我来说，这种办法太麻烦——一个使用 ftrace 的简单例子像是这样：cd /sys/kernel/debug/tracing echo function > current_tracer echo do_page_fault > set_ftrace_filter cat trace 这个文件系统是跟踪系统的接口（“给这些神奇的文件赋值，然后该发生的事情就会发生”）理论上看起来似乎可用，但是它不是我的首选方式。幸运的是，ftrace 团队也考虑到这个并不友好的用户界面，因此，它有了一个更易于使用的界面，它就是 trace-cmd！！！trace-cmd 是一个带命令行参数的普通程序。我们后面将使用它！我在 LWN 上找到了一个 trace-cmd 的使用介绍：trace-cmd: Ftrace 的一个前端。开始使用 trace-cmd：让我们仅跟踪一个函数首先，我需要去使用 sudo apt-get install trace-cmd 安装 trace-cmd，这一步很容易。对于第一个 ftrace 的演示，我决定去了解我的内核如何去处理一个页面故障。当 Linux 分配内存时，它经常偷懒，（“你并不是真的计划去使用内存，对吗？”）。这意味着，当一个应用程序尝试去对分配给它的内存进行写入时，就会发生一个页面故障，而这个时候，内核才会真正的为应用程序去分配物理内存。我们开始使用 trace-cmd 并让它跟踪 do_page_fault 函数！$ sudo trace-cmd record -p function -l do_page_fault plugin 'function' Hit Ctrl^C to stop recording 我将它运行了几秒钟，然后按下了 Ctrl+C。 让我大吃一惊的是，它竟然产生了一个 2.5MB 大小的名为 trace.dat 的跟踪文件。我们来看一下这个文件的内容！$ sudo trace-cmd report chrome-15144 [000] 11446.466121: function: do_page_fault chrome-15144 [000] 11446.467910: function: do_page_fault chrome-15144 [000] 11446.469174: function: do_page_fault chrome-15144 [000] 11446.474225: function: do_page_fault chrome-15144 [000] 11446.474386: function: do_page_fault chrome-15144 [000] 11446.478768: function: do_page_fault CompositorTileW-15154 [001] 11446.480172: function…

Linux 中的 DTrace ：BPF 进入 4.9 内核
type: item
date: 2016-12-15T20:22:00+08:00
description: 本文作者 Brendan Gregg 目前是 Netflix 的高级性能架构师 ，他在那里做大规模计算机性能设计、分析和调优。他是《Systems Performance》等技术书的作者，因在系统管理员方面的成绩，获得过 2013年 USENIX LISA 大奖。他之前是 SUN 公司是性能领头人和内核工程师，研究存储和网络性能。他也发明和开发过一大波性能分析工具，很多已集成到操作系统中了 。随着 BPF 追踪系统（基于时间采样）最后一个主要功能被合并至 Linux 4.9-rc1 版本的内核中，现在 Linux 内核拥有类似 DTrace 的原生追踪功能。DTrace 是 Solaris 系统中的高级追踪器。对于长期使用 DTrace 的用户和专家，这将是一个振奋人心的里程碑！现在在 Linux 系统上，你可以在生产环境中使用安全的、低负载的定制追踪系统，通过执行时间的柱状图和频率统计等信息，分析应用的性能以及内核。用于 Linux 的追踪项目有很多，但是这个最终被合并进 Linux 内核的技术从一开始就根本不是一个追踪项目：它是最开始是用于 伯克利包过滤器 （ Berkeley Packet Filter ） （BPF）的增强功能。这些补丁允许 BPF 重定向数据包，从而创建软件定义网络（SDN）。久而久之，对事件追踪的支持就被添加进来了，使得程序追踪可用于 Linux 系统。尽管目前 BPF 没有像 DTrace 一样的高级语言，但它所提供的前端已经足够让我创建很多 BPF 工具了，其中有些是基于我以前的 DTraceToolkit。这个帖子将告诉你怎么去用这些 BPF 提供的前端工具，以及畅谈这项技术将会何去何从。示例我已经将基于 BPF 的追踪工具添加到了开源的 bcc 项目里（感谢 PLUMgrid 公司的 Brenden Blanco 带领 bcc 项目的发展）。详见 bcc 安装 手册。它会在 /usr/share/bcc/tools 目录下添加一系列工具，包括接下来的那些工具。捕获新进程：# execsnoop PCOMM PID RET ARGS bash 15887 0 /usr/bin/man ls preconv 15894 0 /usr/bin/preconv -e UTF-8 man 15896 0 /usr/bin/tbl man 15897 0 /usr/bin/nroff -mandoc -rLL=169n -rLT=169n -Tutf8 man 15898 0 /usr/bin/pager -s nroff 15900 0 /usr/bin/locale charmap nroff 15901 0 /usr/bin/groff -mtty-char -Tutf8 -mandoc -rLL=169n -rLT=169n groff 15902 0 /usr/bin/troff -mtty-char -mandoc -rLL=169n -rLT=169n -Tutf8 groff 15903 0 /usr/bin/grotty 硬盘 I/O 延迟的柱状图：# biolatency -m Tracing block device I/O... Hit Ctrl-C to end. ^C msecs : count distribution 0 -> 1 : 96 |************************************ | 2 -> 3 : 25 |********* | 4 -> 7 : 29 |*********** | 8 -> 15 : 62 |*********************** | 16 -> 31 : 100 |**************************************| 32 -> 63 : 62 |*********************** | 64 -> 127 : 18 |****** | 追踪慢于 5 毫秒的 ext4 常见操作：# ext4slower 5 Tracing ext4 operations slower than 5 ms TIME COMM PID T BYTES OFF_KB LAT(ms) FILENAME 21:49:45 supervise 3570 W 18 0 5.48 status.new 21:49:48 supervise 12770 R 128 0 7.55 run 21:49:48 run 12770 R 497 0 16.46 nsswitch.conf 21:49:48 run 12770 R 1680 0 17.42 netflix_environment.sh 21:49:…

使用 Linux 的 strace 命令跟踪/调试程序的常用选项
type: item
date: 2014-10-01T06:30:00+08:00
description: 在调试的时候，strace能帮助你追踪到一个程序所执行的系统调用。当你想知道程序和操作系统如何交互的时候，这是极其方便的，比如你想知道执行了哪些系统调用，并且以何种顺序执行。这个简单而又强大的工具几乎在所有的Linux操作系统上可用，并且可被用来调试大量的程序。命令用法让我们看看strace命令如何追踪一个程序的执行情况。最简单的形式，strace后面可以跟任何命令。它将列出许许多多的系统调用。一开始，我们并不能理解所有的输出，但是如果你正在寻找一些特殊的东西，那么你应该能从输出中发现它。让我们来看看简单命令ls的系统调用跟踪情况。raghu@raghu-Linoxide ~ $ strace ls 这是strace命令输出的前几行。其他输出被截去了。上面的输出部分展示了write系统调用，它把当前目录的列表输出到标准输出。下面的图片展示了使用ls命令列出的目录内容（没有使用strace）。raghu@raghu-Linoxide ~ $ ls 选项1 寻找被程序读取的配置文件Strace 的用法之一（除了调试某些问题以外）是你能找到被一个程序读取的配置文件。例如，raghu@raghu-Linoxide ~ $ strace php 2>&1 | grep php.ini 选项2 跟踪指定的系统调用strace命令的-e选项仅仅被用来展示特定的系统调用（例如，open，write等等）让我们跟踪一下cat命令的‘open’系统调用。raghu@raghu-Linoxide ~ $ strace -e open cat dead.letter 选项3 跟踪进程strace不但能用在命令上，而且通过使用-p选项能用在运行的进程上。raghu@raghu-Linoxide ~ $ sudo strace -p 1846 选项4 strace的统计概要它包括系统调用的概要，执行时间，错误等等。使用-c选项能够以一种整洁的方式展示：raghu@raghu-Linoxide ~ $ strace -c ls 选项5 保存输出结果通过使用-o选项可以把strace命令的输出结果保存到一个文件中。raghu@raghu-Linoxide ~ $ sudo strace -o process_strace -p 3229 之所以以sudo来运行上面的命令，是为了防止用户ID与所查看进程的所有者ID不匹配的情况。选项6 显示时间戳使用-t选项，可以在每行的输出之前添加时间戳。raghu@raghu-Linoxide ~ $ strace -t ls 选项7 更精细的时间戳-tt选项可以展示微秒级别的时间戳。raghu@raghu-Linoxide ~ $ strace -tt ls -ttt也可以向上面那样展示微秒级的时间戳，但是它并不是打印当前时间，而是显示自从epoch（译注：1970年1月1日00:00:00 UTC）以来的所经过的秒数。raghu@raghu-Linoxide ~ $ strace -ttt ls 选项8 相对时间-r选项展示系统调用之间的相对时间戳。raghu@raghu-Linoxide ~ $ strace -r ls via: http://linoxide.com/linux-command/linux-strace-command-examples/作者：Raghu 译者：guodongxiaren 校对：wxy本文由 LCTT 原创翻译，Linux中国 荣誉推出