This commit is contained in:
yunwei37
2024-09-27 18:36:58 +00:00
parent 5371b7c6a9
commit 252625d27c
4 changed files with 275 additions and 237 deletions

View File

@@ -173,138 +173,157 @@
<div id="content" class="content">
<main>
<h1 id="ebpf-入门开发实践教程零介绍-ebpf-的基本概念常见的开发工具"><a class="header" href="#ebpf-入门开发实践教程零介绍-ebpf-的基本概念常见的开发工具">eBPF 入门开发实践教程零:介绍 eBPF 的基本概念、常见的开发工具</a></h1>
<h2 id="1-ebpf-简介安全和有效地扩展内核"><a class="header" href="#1-ebpf-简介安全和有效地扩展内核">1. eBPF 简介:安全和有效地扩展内核</a></h2>
<p>eBPF 是一项革命性的技术,起源于 Linux 内核可以在操作系统的内核中运行沙盒程序。它被用来安全和有效地扩展内核的功能而不需要改变内核的源代码或加载内核模块。eBPF 通过允许在操作系统内运行沙盒程序应用程序开发人员可以在运行时可编程地向操作系统动态添加额外的功能。然后操作系统保证安全和执行效率就像在即时编译JIT编译器和验证引擎的帮助下进行本地编译一样。eBPF 程序在内核版本之间是可移植的,并且可以自动更新,从而避免了工作负载中断和节点重启</p>
<p>今天eBPF 被广泛用于各类场景:在现代数据中心和云原生环境中,可以提供高性能的网络包处理和负载均衡;以非常低的资源开销,做到对多种细粒度指标的可观测性,帮助应用程序开发人员跟踪应用程序,为性能故障排除提供洞察力;保障应用程序和容器运行时的安全执行,等等。可能性是无穷的,而 eBPF 在操作系统内核中所释放的创新才刚刚开始[3]。</p>
<h3 id="ebpf-的未来内核的-javascript-可编程接口"><a class="header" href="#ebpf-的未来内核的-javascript-可编程接口">eBPF 的未来:内核的 JavaScript 可编程接口</a></h3>
<p>对于浏览器而言JavaScript 的引入带来的可编程性开启了一场巨大的革命,使浏览器发展成为几乎独立的操作系统。现在让我们回到 eBPF为了理解 eBPF 对 Linux 内核的可编程性影响,对 Linux 内核的结构以及它如何与应用程序和硬件进行交互有一个高层次的理解是有帮助的[4]。</p>
<p><img src="kernel-arch.png" alt="kernel-arch" /></p>
<p>Linux 内核的主要目的是抽象出硬件或虚拟硬件,并提供一个一致的 API系统调用允许应用程序运行和共享资源。为了实现这个目的我们维护了一系列子系统和层以分配这些责任[5]。每个子系统通常允许某种程度的配置,以考虑到用户的不同需求。如果不能配置所需的行为,就需要改变内核,从历史上看,改变内核的行为,或者让用户编写的程序能够在内核中运行,就有两种选择:</p>
<div class="table-wrapper"><table><thead><tr><th>本地支持内核模块</th><th>写一个内核模块</th></tr></thead><tbody>
<tr><td>改变内核源代码并说服Linux内核社区相信这种改变是必要的。等待几年让新的内核版本成为一种商品。</td><td>定期修复它因为每个内核版本都可能破坏它。由于缺乏安全边界冒着破坏你的Linux内核的风险</td></tr>
</tbody></table>
</div>
<p>实际上,两种方案都不常用,前者成本太高,后者则几乎没有可移植性。</p>
<p>有了 eBPF就有了一个新的选择可以重新编程 Linux 内核的行为,而不需要改变内核的源代码或加载内核模块,同时保证在不同内核版本之间一定程度上的行为一致性和兼容性、以及安全性[6]。为了实现这个目的eBPF 程序也需要有一套对应的 API允许用户定义的应用程序运行和共享资源 --- 换句话说,某种意义上讲 eBPF 虚拟机也提供了一套类似于系统调用的机制,借助 eBPF 和用户态通信的机制Wasm 虚拟机和用户态应用也可以获得这套“系统调用”的完整使用权,一方面能可编程地扩展传统的系统调用的能力,另一方面能在网络、文件系统等许多层次实现更高效的可编程 IO 处理。</p>
<p><img src="new-os-model.png" alt="new-os" /></p>
<p>正如上图所示,当今的 Linux 内核正在向一个新的内核模型演化:用户定义的应用程序可以在内核态和用户态同时执行,用户态通过传统的系统调用访问系统资源,内核态则通过 BPF Helper Calls 和系统的各个部分完成交互。截止 2023 年初,内核中的 eBPF 虚拟机中已经有 220 多个 Helper 系统接口,涵盖了非常多的应用场景。</p>
<p>值得注意的是BPF Helper Call 和系统调用二者并不是竞争关系,它们的编程模型和有性能优势的场景完全不同,也不会完全替代对方。对 Wasm 和 Wasi 相关生态来说,情况也类似,专门设计的 Wasi 接口需要经历一个漫长的标准化过程,但可能在特定场景能为用户态应用获取更佳的性能和可移植性保证,而 eBPF 在保证沙箱本质和可移植性的前提下,可以提供一个快速灵活的扩展系统接口的方案。</p>
<p>目前的 eBPF 仍然处于早期阶段,但是借助当前 eBPF 提供的内核接口和用户态交互的能力,经由 Wasm-bpf 的系统接口转换Wasm 虚拟机中的应用已经几乎有能力获取内核以及用户态任意一个函数调用的数据和返回值kprobeuprobe...以很低的代价收集和理解所有系统调用并获取所有网络操作的数据包和套接字级别的数据tracepointsocket...在网络包处理解决方案中添加额外的协议分析器并轻松地编程任何转发逻辑XDPTC...以满足不断变化的需求而无需离开Linux内核的数据包处理环境。</p>
<p>不仅如此eBPF 还有能力往用户空间任意进程的任意地址写入数据bpf_probe_write_user[7]有限度地修改内核函数的返回值bpf_override_return[8]),甚至在内核态直接执行某些系统调用[9]所幸的是eBPF 在加载进内核之前对字节码会进行严格的安全检查,确保没有内存越界等操作,同时,许多可能会扩大攻击面、带来安全风险的功能都是需要在编译内核时明确选择启用才能使用的;在 Wasm 虚拟机将字节码加载进内核之前,也可以明确选择启用或者禁用某些 eBPF 功能,以确保沙箱的安全性。</p>
<p>除了内核态的 eBPF 运行时eBPF 也可以拓展到用户空间,例如 <a href="https://github.com/eunomia-bpf/bpftime">bpftime</a>,实现更高性能的用户态追踪、性能分析、插件等等。</p>
<h2 id="2-关于如何学习-ebpf-相关的开发的一些建议"><a class="header" href="#2-关于如何学习-ebpf-相关的开发的一些建议">2. 关于如何学习 eBPF 相关的开发的一些建议</a></h2>
<p>本文不会对 eBPF 的原理做更详细的介绍,不过这里有一个学习规划和参考资料,也许会有一些价值:</p>
<h3 id="ebpf-入门5-7h"><a class="header" href="#ebpf-入门5-7h">eBPF 入门5-7h</a></h3>
<h1 id="ebpf-示例教程-0核心概念与工具简介"><a class="header" href="#ebpf-示例教程-0核心概念与工具简介">eBPF 示例教程 0核心概念与工具简介</a></h1>
<p>这是一个全面的 eBPF 开发教程的第一部分,旨在通过实用的 eBPF 开发指导您从初学者到高级用户。它涵盖了基本概念、实际代码示例以及在现代系统中的应用。我们将不再专注于传统工具如 BCC而是使用现代框架如 <code>libbpf</code><code>Cilium</code><code>libbpf-rs</code> 和 eunomia-bpf并提供 <code>C</code><code>Go</code><code>Rust</code> 的示例。</p>
<p>本教程的主要目标是提供清晰简洁的 eBPF 工具示例(起步只需 20 行代码!),帮助开发者快速掌握基本的 eBPF 开发技术。每个示例都是独立的,可以在目录结构中找到,每个目录代表一个独立的 eBPF 工具。您还可以访问我们的教程代码仓库 <a href="https://github.com/eunomia-bpf/bpf-developer-tutorial">https://github.com/eunomia-bpf/bpf-developer-tutorial</a> 或网站 <a href="https://eunomia.dev/tutorials/">https://eunomia.dev/tutorials/</a> 获取更多示例和完整的教程源代码</p>
<h2 id="ebpf-简介安全高效的内核扩展"><a class="header" href="#ebpf-简介安全高效的内核扩展">eBPF 简介:安全高效的内核扩展</a></h2>
<p>eBPF扩展的 Berkeley Packet Filter是一项突破性的技术允许开发者在内核空间中安全高效地运行小型程序。与传统方法需要修改内核源代码或加载新模块不同eBPF 使得动态定制和优化网络行为成为可能,且不会中断系统操作。这种灵活性和高效性使 eBPF 成为克服传统网络栈限制的关键技术。</p>
<h3 id="ebpf-的强大之处是什么"><a class="header" href="#ebpf-的强大之处是什么">eBPF 的强大之处是什么?</a></h3>
<ul>
<li>Google 或者其他搜索引擎查找eBPF</li>
<li>询问 ChatGPT 之类的东西eBPF 是什么?</li>
<li><strong>直接内核交互</strong>eBPF 程序在内核中执行,与系统级事件如网络包、系统调用或追踪点交互。</li>
<li><strong>安全执行</strong>eBPF 通过验证器在程序运行前检查其逻辑,防止潜在的内核崩溃或安全漏洞。</li>
<li><strong>最低开销</strong>eBPF 通过使用即时编译器JIT将 eBPF 字节码转换为针对特定架构的优化机器码,实现近原生执行速度。</li>
</ul>
<h2 id="ebpf过去现在与未来"><a class="header" href="#ebpf过去现在与未来">eBPF过去、现在与未来</a></h2>
<h3 id="过去可编程网络的变革"><a class="header" href="#过去可编程网络的变革">过去:可编程网络的变革</a></h3>
<p>eBPF 于 2014 年推出彻底改变了开发者处理网络的方式允许小型可编程内核空间应用程序实时处理数据包。通过钩住关键内核点eBPF 使得在网络包到达时应用自定义逻辑成为可能,从而提高了效率和灵活性。这使得组织能够在不需要自定义驱动程序或修改内核的情况下定制网络行为,为云原生和数据中心环境创造了理想的解决方案。</p>
<h3 id="现在满足现代计算需求的多功能框架"><a class="header" href="#现在满足现代计算需求的多功能框架">现在:满足现代计算需求的多功能框架</a></h3>
<p>eBPF 已发展为一个多功能框架超越了其最初的网络用途现在涵盖了可观测性、追踪、安全性甚至系统资源管理。eBPF 程序可以动态钩住内核事件,赋予开发者精确控制系统行为和性能优化的能力,而无需修改内核或重启系统。这使得 eBPF 成为系统管理员和开发者监控、优化和保护环境的必备工具。</p>
<p>以下是 eBPF 目前广泛应用的一些关键领域:</p>
<ul>
<li>
<p><strong>网络</strong>eBPF 提供内核中实时、高速的数据包过滤和处理,允许创建自定义协议解析器和网络策略,无需新驱动程序或系统重启。这在云和数据中心环境中实现了高效的网络管理。</p>
</li>
<li>
<p><strong>可观测性</strong>eBPF 使开发者能够通过收集自定义指标和执行内核级数据聚合来深入了解系统行为。通过利用内核追踪点和函数调用eBPF 有助于识别性能问题和定位难以发现的错误。</p>
</li>
<li>
<p><strong>追踪与分析</strong>eBPF 提供强大的追踪和分析能力,通过附加到内核函数、追踪点甚至用户空间探针,使开发者能够深入了解系统和应用程序的行为,从而优化性能和解决复杂的系统问题。</p>
</li>
<li>
<p><strong>安全</strong>eBPF 在实时安全监控中发挥重要作用。它能够深入检查系统调用、网络流量和其他内核活动,帮助执行动态安全策略和检测异常行为,为基础设施提供高效的保护。</p>
</li>
<li>
<p><strong>调度器优化</strong>eBPF 越来越多地用于增强 CPU 调度,能够监控 CPU 负载并优化任务在核心之间的分配。这可以更有效地利用 CPU 资源,提高系统响应能力。</p>
</li>
<li>
<p><strong>HID人机接口设备驱动增强</strong>:开发者使用 eBPF 优化键盘、鼠标和触摸屏等设备的 HID 驱动程序。通过为处理输入事件添加自定义逻辑eBPF 提高了对延迟敏感应用的响应速度。</p>
</li>
</ul>
<p>各行业组织已大规模采用 eBPF</p>
<ul>
<li><strong>Google</strong>:使用 eBPF 进行安全审计、数据包处理、实时性能监控以及优化其庞大基础设施的 CPU 调度。</li>
<li><strong>Netflix</strong>:利用 eBPF 进行网络流量分析,确保流媒体服务的高可用性和性能。</li>
<li><strong>Android</strong>:应用 eBPF 优化网络使用、功耗和资源分配,提升数百万设备的性能和电池寿命。</li>
<li><strong>S&amp;P Global</strong>:通过 <strong>Cilium</strong> 使用 eBPF 管理跨多个云和本地系统的网络,确保可扩展性和安全性。</li>
<li><strong>Shopify</strong>:与 <strong>Falco</strong> 一起实施 eBPF 进行入侵检测,增强其电子商务平台的安全性。</li>
<li><strong>Cloudflare</strong>:使用 eBPF 进行网络可观测性、安全监控和性能优化,保护全球数百万网站。</li>
</ul>
<p>eBPF 能够动态调整系统行为并扩展到用户空间使其成为现代计算不可或缺的技术。无论是优化网络流量、提升安全性还是增强系统性能eBPF 都能帮助开发者高效、安全地应对实时需求。</p>
<p>除了其内核模式运行时eBPF 还可以扩展到用户空间。例如,<a href="https://github.com/eunomia-bpf/bpftime">bpftime</a> 是一个用户空间 eBPF 运行时,允许在用户空间应用中进行高性能追踪、性能分析和插件支持。这种 eBPF 向用户空间的扩展有助于在各种超越内核级任务的用例中提高灵活性和性能。</p>
<h3 id="未来ebpf-的扩展潜力"><a class="header" href="#未来ebpf-的扩展潜力">未来eBPF 的扩展潜力</a></h3>
<p>展望未来,预计 eBPF 将成为操作系统更为重要的一部分。重点将放在提升其灵活性、模块化和易用性上,使其能够应用于更广泛的场景。内存管理、并发机制的创新以及与用户空间应用的更好集成已在路上。已经有项目在编译 Linux 内核的关键部分到 BPF 指令集,这可能彻底改变内核开发和分析的方式。</p>
<p>动态栈、更好的用户空间可观测性工具(例如快速 Uprobes 和特定语言的栈行走器)以及更安全的程序终止机制等进展将继续增强 eBPF 的可靠性并扩展其使用场景。此外,新工具和库将简化 eBPF 开发,降低内核和应用开发者的入门门槛。</p>
<h2 id="开始学习教程"><a class="header" href="#开始学习教程">开始学习教程</a></h2>
<p>本教程提供实用的 eBPF 开发实践,涵盖从初级到高级的主题。我们专注于在可观测性、网络和安全等领域的动手示例,使用 <code>libbpf</code><code>libbpf-rs</code><code>eunomia-bpf</code> 等框架,并提供 C、Go 和 Rust 的示例。</p>
<h3 id="本教程适合谁"><a class="header" href="#本教程适合谁">本教程适合谁?</a></h3>
<ul>
<li><strong>开发者</strong> 希望实现自定义内核解决方案。</li>
<li><strong>系统管理员</strong> 旨在提升性能和安全性。</li>
<li><strong>技术爱好者</strong> 探索前沿的内核技术。</li>
</ul>
<h3 id="你将学到什么"><a class="header" href="#你将学到什么">你将学到什么?</a></h3>
<ul>
<li><strong>核心概念</strong>eBPF 基础知识及其与 Linux 内核的集成。</li>
<li><strong>实用技能</strong>:编写和部署 eBPF 程序。</li>
<li><strong>高级主题</strong>:探索 eBPF 在安全、追踪和未来创新方面的应用。</li>
</ul>
<hr />
<h2 id="目录"><a class="header" href="#目录">目录</a></h2>
<ol>
<li>
<p><strong>eBPF 简介</strong><br />
基本概念和入门所需的工具。</p>
</li>
<li>
<p><strong>初学者示例</strong><br />
简单的程序如“Hello World”及使用 kprobe 和 uprobe 进行基础追踪。</p>
</li>
<li>
<p><strong>可观测性</strong><br />
侧重于使用 eBPF 监控网络流量、文件操作和进程行为的示例。</p>
</li>
<li>
<p><strong>网络</strong><br />
侧重于修改和优化网络流量的示例,如 XDP、TC 和 socket。</p>
</li>
<li>
<p><strong>安全</strong><br />
用于隐藏进程和文件、发送信号杀死进程以及跟踪进程事件以增强安全性的程序。</p>
</li>
<li>
<p><strong>高级用例</strong><br />
涉及性能分析、调度器优化和用户空间 eBPF如 bpftime的复杂示例。</p>
</li>
<li>
<p><strong>深入主题</strong><br />
探索 eBPF 在 Android 上的应用、使用 eBPF 进行网络加速以及通过系统调用修改来保护系统。</p>
</li>
</ol>
<h2 id="如何使用-ebpf-编程"><a class="header" href="#如何使用-ebpf-编程">如何使用 eBPF 编程</a></h2>
<p>从头编写 eBPF 程序可能较为复杂。为简化这一过程LLVM 于 2015 年引入了将高级语言代码编译为 eBPF 字节码的能力。自那时起eBPF 社区构建了像 <code>libbpf</code> 这样的库来管理这些程序。这些库帮助将 eBPF 字节码加载到内核中并执行基本任务。Linux 内核源代码中 <code>samples/bpf/</code> 目录包含了众多 eBPF 示例。</p>
<p>典型的 eBPF 程序包含两个部分:内核空间代码(<code>*_kern.c</code>)和用户空间代码(<code>*_user.c</code>)。内核空间代码定义逻辑,而用户空间代码负责加载和与内核交互。然而,像 <code>libbpf-bootstrap</code> 和 Go eBPF 库这样的工具简化了这一过程,允许一次性编译和更容易的开发。</p>
<h3 id="ebpf-开发工具"><a class="header" href="#ebpf-开发工具">eBPF 开发工具</a></h3>
<ul>
<li><strong>BCC</strong>:一个基于 Python 的工具链,简化了 eBPF 程序的编写、编译和加载。它提供了许多预构建的追踪工具,但在依赖和兼容性方面存在一些限制。</li>
<li><strong>eBPF Go 库</strong>:一个 Go 库,解耦了获取 eBPF 字节码的过程与加载和管理 eBPF 程序的过程。</li>
<li><strong>libbpf-bootstrap</strong>:基于 <code>libbpf</code> 的现代脚手架,提供了高效的工作流用于编写 eBPF 程序,提供简单的一次性编译过程以生成可重用的字节码。</li>
<li><strong>eunomia-bpf</strong>:一个用于编写仅包含内核空间代码的 eBPF 程序的工具链。它通过动态加载 eBPF 程序简化了 eBPF 程序的开发。</li>
</ul>
<p>这些工具有助于减少开发 eBPF 程序的复杂性,使开发者更容易优化系统性能、安全性和可观测性。</p>
<h2 id="学习-ebpf-开发的一些技巧"><a class="header" href="#学习-ebpf-开发的一些技巧">学习 eBPF 开发的一些技巧</a></h2>
<p>本文不会提供更详细的 eBPF 原理介绍,但以下是一个学习计划和参考资料,可能对您有帮助:</p>
<h3 id="ebpf-简介5-7-小时"><a class="header" href="#ebpf-简介5-7-小时">eBPF 简介5-7 小时)</a></h3>
<ul>
<li>使用 Google 或其他搜索引擎搜索eBPF</li>
<li>询问类似 ChatGPT 的工具:什么是 eBPF</li>
</ul>
<p>推荐:</p>
<ul>
<li>阅读 ebpf 简介<a href="https://ebpf.io/">https://ebpf.io/</a> 30min</li>
<li>简要了解一下 ebpf 内核相关文档:<a href="https://prototype-kernel.readthedocs.io/en/latest/bpf/">https://prototype-kernel.readthedocs.io/en/latest/bpf/</a> 知道有问题去哪里查询30min</li>
<li>阅读 ebpf 中文入门指南:<a href="https://www.ebpf.top/post/ebpf_intro">https://www.ebpf.top/post/ebpf_intro</a> 1h</li>
<li>有大量的参考资料:<a href="https://github.com/zoidbergwill/awesome-ebpf">https://github.com/zoidbergwill/awesome-ebpf</a> 2-3h</li>
<li>可以选自己感兴趣的 PPT 翻一翻:<a href="https://github.com/gojue/ebpf-slide">https://github.com/gojue/ebpf-slide</a> 1-2h</li>
<li>阅读 eBPF 介绍<a href="https://ebpf.io/">https://ebpf.io/</a>30 分钟</li>
<li>简要了解 eBPF 内核相关文档:<a href="https://docs.ebpf.io/">https://docs.ebpf.io/</a>了解技术细节的查询来源30 分钟</li>
</ul>
<p>回答三个问题:</p>
<ol>
<li>了解 eBPF 是什么东西?为啥要有这个玩意,不能用内核模块?</li>
<li>它有什么功能?在 Linux 内核里面完成哪些事情?有哪些 eBPF 程序的类型和 helper不需要知道全部,但需要知道哪里找)?</li>
<li>能拿来做什么?比如说在哪些场景中进行运用?网络、安全、可观测性?</li>
<li>了解 eBPF 是什么?我们为什么需要它?难道不能使用内核模块</li>
<li>它有哪些功能?在 Linux 内核中能做什么eBPF 程序和助手函数有哪些类型(不需要全部了解,但需要知道哪里找)?</li>
<li>它能用于哪些场景?例如,可以在哪些情况下使用?网络、安全、可观测性?</li>
</ol>
<h3 id="解如何开发-ebpf-程序10-15h"><a class="header" href="#解如何开发-ebpf-程序10-15h">解如何开发 eBPF 程序10-15h</a></h3>
<p>了解并尝试一下 eBPF 开发框架:</p>
<h3 id="解如何开发-ebpf-程序10-15-小时"><a class="header" href="#解如何开发-ebpf-程序10-15-小时">解如何开发 eBPF 程序10-15 小时</a></h3>
<p>了解并尝试 eBPF 开发框架:</p>
<ul>
<li>bpftrace 教程对于最简单的应用来说bpftrace 可能是最方便的<a href="https://eunomia.dev/zh/tutorials/bpftrace-tutorial/">https://eunomia.dev/zh/tutorials/bpftrace-tutorial/</a> 试试1h</li>
<li>BCC 开发各类小工具的例<a href="https://github.com/iovisor/bcc/blob/master/docs/tutorial_bcc_python_developer.md">https://github.com/iovisor/bcc/blob/master/docs/tutorial_bcc_python_developer.md</a> (跑一遍3-4h</li>
<li>libbpf 的一些例<a href="https://github.com/libbpf/libbpf-bootstrap">https://github.com/libbpf/libbpf-bootstrap</a> (选感兴趣的运行一下,并阅读一下源代码2h</li>
<li>基于 C 语言 libbpf, Go 语言或者 Rust 语言和 eunomia-bpf 的教程:<a href="https://github.com/eunomia-bpf/bpf-developer-tutorial">https://github.com/eunomia-bpf/bpf-developer-tutorial</a> (阅读 1-20 部分3-8h</li>
<li>bpftrace 教程:<a href="https://eunomia.dev/tutorials/bpftrace-tutorial/">https://eunomia.dev/tutorials/bpftrace-tutorial/</a>尝试1 小时</li>
<li>使用 BCC 开发各工具的例:<a href="https://github.com/iovisor/bcc/blob/master/docs/tutorial_bcc_python_developer.md">https://github.com/iovisor/bcc/blob/master/docs/tutorial_bcc_python_developer.md</a>(运行3-4 小时</li>
<li>libbpf 的一些例:<a href="https://github.com/libbpf/libbpf-bootstrap">https://github.com/libbpf/libbpf-bootstrap</a>(运行任何有趣的示例并阅读源代码2 小时</li>
<li>教程:<a href="https://github.com/eunomia-bpf/bpf-developer-tutorial">https://github.com/eunomia-bpf/bpf-developer-tutorial</a>(阅读 1-10 部分3-4 小时</li>
</ul>
<p>有任何问题或者想了解的东西,不管是不是和本项目相关,都可以在本项目的 discussions 里面开始讨论。</p>
<p>回答一些问题并且进行一些尝试2-5h</p>
<p>其他开发框架Go 或 Rust 语言请自行搜索和尝试0-2 小时)</p>
<p>如果有问题或想了解的内容,无论是否与本项目相关,都可以在该项目的讨论区开始讨论。</p>
<p>回答一些问题并尝试一些实验2-5 小时):</p>
<ol>
<li>如何开发一个最简单的 eBPF 程序?</li>
<li>如何用 eBPF 追踪一个内核功能或函数?有很多方法,举出对应的代码;</li>
<li>有哪些方案能通过用户态和内核态通信?如何从用户态向内核态传送信息?如何从内核态向用户态传递信息?举出代码示例;</li>
<li>编写一个你自己的 eBPF 程序实现个功能;</li>
<li>eBPF 程序的整个生命周期里面,分别在用户态和内核态做了哪些事情</li>
<li>如何开发最简单的 eBPF 程序?</li>
<li>如何使用 eBPF 追踪内核功能或函数?有很多方法,提供相应的代码示例</li>
<li>用户模式和内核模式之间的通信解决方案有哪些?如何将信息从用户模式发送到内核模式?如何将信息从内核模式传递到用户模式?提供代码示例;</li>
<li>编写自己的 eBPF 程序实现个功能;</li>
<li>eBPF 程序的整个生命周期中,用户模式和内核模式分别做了什么</li>
</ol>
<h2 id="3-如何使用-ebpf-编程"><a class="header" href="#3-如何使用-ebpf-编程">3. 如何使用 eBPF 编程</a></h2>
<p>原始的 eBPF 程序编写是非常繁琐和困难的。为了改变这一现状llvm 于 2015 年推出了可以将由高级语言编写的代码编译为 eBPF 字节码的功能同时eBPF 社区将 <code>bpf()</code> 等原始的系统调用进行了初步地封装,给出了 <code>libbpf</code> 库。这些库会包含将字节码加载到内核中的函数以及一些其他的关键函数。在 Linux 的源码包的 <code>samples/bpf/</code> 目录下,有大量 Linux 提供的基于 <code>libbpf</code> 的 eBPF 样例代码。</p>
<p>一个典型的基于 <code>libbpf</code> 的 eBPF 程序具有 <code>*_kern.c</code><code>*_user.c</code> 两个文件,<code>*_kern.c</code> 中书写在内核中的挂载点以及处理函数,<code>*_user.c</code> 中书写用户态代码,完成内核态代码注入以及与用户交互的各种任务。 更为详细的教程可以参考<a href="https://www.bilibili.com/video/BV1f54y1h74r?spm_id_from=333.999.0.0">该视频</a>。然而由于该方法仍然较难理解且入门存在一定的难度因此现阶段的eBPF程序开发大多基于一些工具比如</p>
<ul>
<li>BCC</li>
<li>BPFtrace</li>
<li>libbpf-bootstrap</li>
<li>Go eBPF library</li>
</ul>
<p>以及还有比较新的工具,例如 <code>eunomia-bpf</code>.</p>
<h2 id="编写-ebpf-程序"><a class="header" href="#编写-ebpf-程序">编写 eBPF 程序</a></h2>
<p>eBPF 程序由内核态部分和用户态部分构成。内核态部分包含程序的实际逻辑,用户态部分负责加载和管理内核态部分。使用 eunomia-bpf 开发工具,只需编写内核态部分的代码。</p>
<p>内核态部分的代码需要符合 eBPF 的语法和指令集。eBPF 程序主要由若干个函数组成,每个函数都有其特定的作用。可以使用的函数类型包括:</p>
<ul>
<li>kprobe插探函数在指定的内核函数前或后执行。</li>
<li>tracepoint跟踪点函数在指定的内核跟踪点处执行。</li>
<li>raw_tracepoint原始跟踪点函数在指定的内核原始跟踪点处执行。</li>
<li>xdp网络数据处理函数拦截和处理网络数据包。</li>
<li>perf_event性能事件函数用于处理内核性能事件。</li>
<li>kretprobe函数返回插探函数在指定的内核函数返回时执行。</li>
<li>tracepoint_return跟踪点函数返回在指定的内核跟踪点返回时执行。</li>
<li>raw_tracepoint_return原始跟踪点函数返回在指定的内核原始跟踪</li>
</ul>
<h3 id="bcc"><a class="header" href="#bcc">BCC</a></h3>
<p>BCC 全称为 BPF Compiler Collection该项目是一个 python 库,
包含了完整的编写、编译、和加载 BPF 程序的工具链,以及用于调试和诊断性能问题的工具。</p>
<p>自 2015 年发布以来BCC 经过上百位贡献者地不断完善后,目前已经包含了大量随时可用的跟踪工具。<a href="https://github.com/iovisor/bcc/blob/master/docs/tutorial.md">其官方项目库</a>
提供了一个方便上手的教程,用户可以快速地根据教程完成 BCC 入门工作。</p>
<p>用户可以在 BCC 上使用 Python、Lua 等高级语言进行编程。
相较于使用 C 语言直接编程,这些高级语言具有极大的便捷性,用户只需要使用 C 来设计内核中的
BPF 程序,其余包括编译、解析、加载等工作在内,均可由 BCC 完成。</p>
<p>然而使用 BCC 存在一个缺点便是在于其兼容性并不好。基于 BCC 的
eBPF 程序每次执行时候都需要进行编译,编译则需要用户配置相关的头文件和对应实现。在实际应用中,
相信大家也会有体会,编译依赖问题是一个很棘手的问题。也正是因此,在本项目的开发中我们放弃了 BCC
选择了可以做到一次编译-多次运行的 libbpf-bootstrap 工具。</p>
<h3 id="ebpf-go-library"><a class="header" href="#ebpf-go-library">eBPF Go library</a></h3>
<p>eBPF Go 库提供了一个通用的 eBPF 库,它解耦了获取 eBPF 字节码的过程和 eBPF 程序的加载和管理,并实现了类似 libbpf 一样的 CO- 功能。eBPF 程序通常是通过编写高级语言创建的,然后使用 clang/LLVM 编译器编译为 eBPF 字节码。</p>
<h3 id="libbpf"><a class="header" href="#libbpf">libbpf</a></h3>
<p><code>libbpf-bootstrap</code> 是一个基于 <code>libbpf</code> 库的 BPF 开发脚手架,从其
<a href="https://github.com/libbpf/libbpf-bootstrap">github</a> 上可以得到其源码。</p>
<p><code>libbpf-bootstrap</code> 综合了 BPF 社区过去多年的实践,为开发者提了一个现代化的、便捷的工作流,实
现了一次编译,重复使用的目的。</p>
<p>基于 <code>libbpf-bootstrap</code> 的 BPF 程序对于源文件有一定的命名规则,
用于生成内核态字节码的 bpf 文件以 <code>.bpf.c</code> 结尾,用户态加载字节码的文件以 <code>.c</code> 结尾,且这两个文件的
前缀必须相同。</p>
<p>基于 <code>libbpf-bootstrap</code> 的 BPF 程序在编译时会先将 <code>*.bpf.c</code> 文件编译为
对应的 <code>.o</code> 文件,然后根据此文件生成 <code>skeleton</code> 文件,即 <code>*.skel.h</code>,这个文件会包含内核态中定义的一些
数据结构,以及用于装载内核态代码的关键函数。在用户态代码 <code>include</code> 此文件之后调用对应的装载函数即可将
字节码装载到内核中。同样的,<code>libbpf-bootstrap</code> 也有非常完备的入门教程,用户可以在<a href="https://nakryiko.com/posts/libbpf-bootstrap/">该处</a>
得到详细的入门操作介绍。</p>
<h3 id="eunomia-bpf"><a class="header" href="#eunomia-bpf">eunomia-bpf</a></h3>
<p><a href="https://github.com/eunomia-bpf/eunomia-bpf">eunomia-bpf</a> 是一个开源的 eBPF 动态加载运行时和开发工具链,是为了简化 eBPF 程序的开发、构建、分发、运行而设计的,基于 libbpf 的 CO-RE 轻量级开发框架。</p>
<p>使用 eunomia-bpf ,可以:</p>
<ul>
<li>在编写 eBPF 程序或工具时只编写内核态代码,自动获取内核态导出信息,并作为模块动态加载;</li>
<li>eunomia-bpf 可以将预编译的 eBPF 程序打包为通用的 JSON 或 WASM 模块,跨架构和内核版本进行分发,无需重新编译即可动态加载运行。</li>
</ul>
<p>eunomia-bpf 由一个编译工具链和一个运行时库组成, 对比传统的 BCC、原生 libbpf 等框架,简化了 eBPF 程序的开发流程,在大多数时候只需编写内核态代码,即可轻松构建、打包、发布完整的 eBPF 应用。</p>
<blockquote>
<ul>
<li>eunomia-bpf 项目 Github 地址: <a href="https://github.com/eunomia-bpf/eunomia-bpf">https://github.com/eunomia-bpf/eunomia-bpf</a></li>
<li>gitee 镜像: <a href="https://gitee.com/anolis/eunomia">https://gitee.com/anolis/eunomia</a></li>
</ul>
</blockquote>
<h2 id="参考资料"><a class="header" href="#参考资料">参考资料</a></h2>
<ul>
<li>eBPF 介绍:<a href="https://ebpf.io/">https://ebpf.io/</a></li>
<li>BPF Compiler Collection (BCC)<a href="https://github.com/iovisor/bcc">https://github.com/iovisor/bcc</a></li>
<li>BPF 编译器集合(BCC<a href="https://github.com/iovisor/bcc">https://github.com/iovisor/bcc</a></li>
<li>eunomia-bpf<a href="https://github.com/eunomia-bpf/eunomia-bpf">https://github.com/eunomia-bpf/eunomia-bpf</a></li>
</ul>
<p>您还可以访问我们的教程代码仓库 <a href="https://github.com/eunomia-bpf/bpf-developer-tutorial">https://github.com/eunomia-bpf/bpf-developer-tutorial</a> 或网站 <a href="https://eunomia.dev/zh/tutorials/">https://eunomia.dev/zh/tutorials/</a> 获取更多示例和完整的教程源代码。我们继续分享更多关 eBPF 开发实践的内容,帮助您更好地理解和掌握 eBPF 技术。</p>
<blockquote>
<p>原文地址:<a href="https://eunomia.dev/zh/tutorials/0-introduce/">https://eunomia.dev/zh/tutorials/0-introduce/</a> 转载请注明</p>
</blockquote>
<p>您还可以访问我们的教程代码仓库 <a href="https://github.com/eunomia-bpf/bpf-developer-tutorial">https://github.com/eunomia-bpf/bpf-developer-tutorial</a> 或网站 <a href="https://eunomia.dev/tutorials/">https://eunomia.dev/tutorials/</a> 获取更多示例和完整的教程源代码。所有内容均为开源。我们继续分享更多关 eBPF 开发实践的内容,帮助您更好地理解和掌握 eBPF 技术。</p>
</main>

View File

@@ -175,138 +175,157 @@
<div id="content" class="content">
<main>
<h1 id="httpsgithubcomeunomia-bpfbpf-developer-tutorial"><a class="header" href="#httpsgithubcomeunomia-bpfbpf-developer-tutorial">https://github.com/eunomia-bpf/bpf-developer-tutorial</a></h1>
<div style="break-before: page; page-break-before: always;"></div><h1 id="ebpf-入门开发实践教程零介绍-ebpf-的基本概念常见的开发工具"><a class="header" href="#ebpf-入门开发实践教程零介绍-ebpf-的基本概念常见的开发工具">eBPF 入门开发实践教程零:介绍 eBPF 的基本概念、常见的开发工具</a></h1>
<h2 id="1-ebpf-简介安全和有效地扩展内核"><a class="header" href="#1-ebpf-简介安全和有效地扩展内核">1. eBPF 简介:安全和有效地扩展内核</a></h2>
<p>eBPF 是一项革命性的技术,起源于 Linux 内核可以在操作系统的内核中运行沙盒程序。它被用来安全和有效地扩展内核的功能而不需要改变内核的源代码或加载内核模块。eBPF 通过允许在操作系统内运行沙盒程序应用程序开发人员可以在运行时可编程地向操作系统动态添加额外的功能。然后操作系统保证安全和执行效率就像在即时编译JIT编译器和验证引擎的帮助下进行本地编译一样。eBPF 程序在内核版本之间是可移植的,并且可以自动更新,从而避免了工作负载中断和节点重启</p>
<p>今天eBPF 被广泛用于各类场景:在现代数据中心和云原生环境中,可以提供高性能的网络包处理和负载均衡;以非常低的资源开销,做到对多种细粒度指标的可观测性,帮助应用程序开发人员跟踪应用程序,为性能故障排除提供洞察力;保障应用程序和容器运行时的安全执行,等等。可能性是无穷的,而 eBPF 在操作系统内核中所释放的创新才刚刚开始[3]。</p>
<h3 id="ebpf-的未来内核的-javascript-可编程接口"><a class="header" href="#ebpf-的未来内核的-javascript-可编程接口">eBPF 的未来:内核的 JavaScript 可编程接口</a></h3>
<p>对于浏览器而言JavaScript 的引入带来的可编程性开启了一场巨大的革命,使浏览器发展成为几乎独立的操作系统。现在让我们回到 eBPF为了理解 eBPF 对 Linux 内核的可编程性影响,对 Linux 内核的结构以及它如何与应用程序和硬件进行交互有一个高层次的理解是有帮助的[4]。</p>
<p><img src="0-introduce/kernel-arch.png" alt="kernel-arch" /></p>
<p>Linux 内核的主要目的是抽象出硬件或虚拟硬件,并提供一个一致的 API系统调用允许应用程序运行和共享资源。为了实现这个目的我们维护了一系列子系统和层以分配这些责任[5]。每个子系统通常允许某种程度的配置,以考虑到用户的不同需求。如果不能配置所需的行为,就需要改变内核,从历史上看,改变内核的行为,或者让用户编写的程序能够在内核中运行,就有两种选择:</p>
<div class="table-wrapper"><table><thead><tr><th>本地支持内核模块</th><th>写一个内核模块</th></tr></thead><tbody>
<tr><td>改变内核源代码并说服Linux内核社区相信这种改变是必要的。等待几年让新的内核版本成为一种商品。</td><td>定期修复它因为每个内核版本都可能破坏它。由于缺乏安全边界冒着破坏你的Linux内核的风险</td></tr>
</tbody></table>
</div>
<p>实际上,两种方案都不常用,前者成本太高,后者则几乎没有可移植性。</p>
<p>有了 eBPF就有了一个新的选择可以重新编程 Linux 内核的行为,而不需要改变内核的源代码或加载内核模块,同时保证在不同内核版本之间一定程度上的行为一致性和兼容性、以及安全性[6]。为了实现这个目的eBPF 程序也需要有一套对应的 API允许用户定义的应用程序运行和共享资源 --- 换句话说,某种意义上讲 eBPF 虚拟机也提供了一套类似于系统调用的机制,借助 eBPF 和用户态通信的机制Wasm 虚拟机和用户态应用也可以获得这套“系统调用”的完整使用权,一方面能可编程地扩展传统的系统调用的能力,另一方面能在网络、文件系统等许多层次实现更高效的可编程 IO 处理。</p>
<p><img src="0-introduce/new-os-model.png" alt="new-os" /></p>
<p>正如上图所示,当今的 Linux 内核正在向一个新的内核模型演化:用户定义的应用程序可以在内核态和用户态同时执行,用户态通过传统的系统调用访问系统资源,内核态则通过 BPF Helper Calls 和系统的各个部分完成交互。截止 2023 年初,内核中的 eBPF 虚拟机中已经有 220 多个 Helper 系统接口,涵盖了非常多的应用场景。</p>
<p>值得注意的是BPF Helper Call 和系统调用二者并不是竞争关系,它们的编程模型和有性能优势的场景完全不同,也不会完全替代对方。对 Wasm 和 Wasi 相关生态来说,情况也类似,专门设计的 Wasi 接口需要经历一个漫长的标准化过程,但可能在特定场景能为用户态应用获取更佳的性能和可移植性保证,而 eBPF 在保证沙箱本质和可移植性的前提下,可以提供一个快速灵活的扩展系统接口的方案。</p>
<p>目前的 eBPF 仍然处于早期阶段,但是借助当前 eBPF 提供的内核接口和用户态交互的能力,经由 Wasm-bpf 的系统接口转换Wasm 虚拟机中的应用已经几乎有能力获取内核以及用户态任意一个函数调用的数据和返回值kprobeuprobe...以很低的代价收集和理解所有系统调用并获取所有网络操作的数据包和套接字级别的数据tracepointsocket...在网络包处理解决方案中添加额外的协议分析器并轻松地编程任何转发逻辑XDPTC...以满足不断变化的需求而无需离开Linux内核的数据包处理环境。</p>
<p>不仅如此eBPF 还有能力往用户空间任意进程的任意地址写入数据bpf_probe_write_user[7]有限度地修改内核函数的返回值bpf_override_return[8]),甚至在内核态直接执行某些系统调用[9]所幸的是eBPF 在加载进内核之前对字节码会进行严格的安全检查,确保没有内存越界等操作,同时,许多可能会扩大攻击面、带来安全风险的功能都是需要在编译内核时明确选择启用才能使用的;在 Wasm 虚拟机将字节码加载进内核之前,也可以明确选择启用或者禁用某些 eBPF 功能,以确保沙箱的安全性。</p>
<p>除了内核态的 eBPF 运行时eBPF 也可以拓展到用户空间,例如 <a href="https://github.com/eunomia-bpf/bpftime">bpftime</a>,实现更高性能的用户态追踪、性能分析、插件等等。</p>
<h2 id="2-关于如何学习-ebpf-相关的开发的一些建议"><a class="header" href="#2-关于如何学习-ebpf-相关的开发的一些建议">2. 关于如何学习 eBPF 相关的开发的一些建议</a></h2>
<p>本文不会对 eBPF 的原理做更详细的介绍,不过这里有一个学习规划和参考资料,也许会有一些价值:</p>
<h3 id="ebpf-入门5-7h"><a class="header" href="#ebpf-入门5-7h">eBPF 入门5-7h</a></h3>
<div style="break-before: page; page-break-before: always;"></div><h1 id="ebpf-示例教程-0核心概念与工具简介"><a class="header" href="#ebpf-示例教程-0核心概念与工具简介">eBPF 示例教程 0核心概念与工具简介</a></h1>
<p>这是一个全面的 eBPF 开发教程的第一部分,旨在通过实用的 eBPF 开发指导您从初学者到高级用户。它涵盖了基本概念、实际代码示例以及在现代系统中的应用。我们将不再专注于传统工具如 BCC而是使用现代框架如 <code>libbpf</code><code>Cilium</code><code>libbpf-rs</code> 和 eunomia-bpf并提供 <code>C</code><code>Go</code><code>Rust</code> 的示例。</p>
<p>本教程的主要目标是提供清晰简洁的 eBPF 工具示例(起步只需 20 行代码!),帮助开发者快速掌握基本的 eBPF 开发技术。每个示例都是独立的,可以在目录结构中找到,每个目录代表一个独立的 eBPF 工具。您还可以访问我们的教程代码仓库 <a href="https://github.com/eunomia-bpf/bpf-developer-tutorial">https://github.com/eunomia-bpf/bpf-developer-tutorial</a> 或网站 <a href="https://eunomia.dev/tutorials/">https://eunomia.dev/tutorials/</a> 获取更多示例和完整的教程源代码</p>
<h2 id="ebpf-简介安全高效的内核扩展"><a class="header" href="#ebpf-简介安全高效的内核扩展">eBPF 简介:安全高效的内核扩展</a></h2>
<p>eBPF扩展的 Berkeley Packet Filter是一项突破性的技术允许开发者在内核空间中安全高效地运行小型程序。与传统方法需要修改内核源代码或加载新模块不同eBPF 使得动态定制和优化网络行为成为可能,且不会中断系统操作。这种灵活性和高效性使 eBPF 成为克服传统网络栈限制的关键技术。</p>
<h3 id="ebpf-的强大之处是什么"><a class="header" href="#ebpf-的强大之处是什么">eBPF 的强大之处是什么?</a></h3>
<ul>
<li>Google 或者其他搜索引擎查找eBPF</li>
<li>询问 ChatGPT 之类的东西eBPF 是什么?</li>
<li><strong>直接内核交互</strong>eBPF 程序在内核中执行,与系统级事件如网络包、系统调用或追踪点交互。</li>
<li><strong>安全执行</strong>eBPF 通过验证器在程序运行前检查其逻辑,防止潜在的内核崩溃或安全漏洞。</li>
<li><strong>最低开销</strong>eBPF 通过使用即时编译器JIT将 eBPF 字节码转换为针对特定架构的优化机器码,实现近原生执行速度。</li>
</ul>
<h2 id="ebpf过去现在与未来"><a class="header" href="#ebpf过去现在与未来">eBPF过去、现在与未来</a></h2>
<h3 id="过去可编程网络的变革"><a class="header" href="#过去可编程网络的变革">过去:可编程网络的变革</a></h3>
<p>eBPF 于 2014 年推出彻底改变了开发者处理网络的方式允许小型可编程内核空间应用程序实时处理数据包。通过钩住关键内核点eBPF 使得在网络包到达时应用自定义逻辑成为可能,从而提高了效率和灵活性。这使得组织能够在不需要自定义驱动程序或修改内核的情况下定制网络行为,为云原生和数据中心环境创造了理想的解决方案。</p>
<h3 id="现在满足现代计算需求的多功能框架"><a class="header" href="#现在满足现代计算需求的多功能框架">现在:满足现代计算需求的多功能框架</a></h3>
<p>eBPF 已发展为一个多功能框架超越了其最初的网络用途现在涵盖了可观测性、追踪、安全性甚至系统资源管理。eBPF 程序可以动态钩住内核事件,赋予开发者精确控制系统行为和性能优化的能力,而无需修改内核或重启系统。这使得 eBPF 成为系统管理员和开发者监控、优化和保护环境的必备工具。</p>
<p>以下是 eBPF 目前广泛应用的一些关键领域:</p>
<ul>
<li>
<p><strong>网络</strong>eBPF 提供内核中实时、高速的数据包过滤和处理,允许创建自定义协议解析器和网络策略,无需新驱动程序或系统重启。这在云和数据中心环境中实现了高效的网络管理。</p>
</li>
<li>
<p><strong>可观测性</strong>eBPF 使开发者能够通过收集自定义指标和执行内核级数据聚合来深入了解系统行为。通过利用内核追踪点和函数调用eBPF 有助于识别性能问题和定位难以发现的错误。</p>
</li>
<li>
<p><strong>追踪与分析</strong>eBPF 提供强大的追踪和分析能力,通过附加到内核函数、追踪点甚至用户空间探针,使开发者能够深入了解系统和应用程序的行为,从而优化性能和解决复杂的系统问题。</p>
</li>
<li>
<p><strong>安全</strong>eBPF 在实时安全监控中发挥重要作用。它能够深入检查系统调用、网络流量和其他内核活动,帮助执行动态安全策略和检测异常行为,为基础设施提供高效的保护。</p>
</li>
<li>
<p><strong>调度器优化</strong>eBPF 越来越多地用于增强 CPU 调度,能够监控 CPU 负载并优化任务在核心之间的分配。这可以更有效地利用 CPU 资源,提高系统响应能力。</p>
</li>
<li>
<p><strong>HID人机接口设备驱动增强</strong>:开发者使用 eBPF 优化键盘、鼠标和触摸屏等设备的 HID 驱动程序。通过为处理输入事件添加自定义逻辑eBPF 提高了对延迟敏感应用的响应速度。</p>
</li>
</ul>
<p>各行业组织已大规模采用 eBPF</p>
<ul>
<li><strong>Google</strong>:使用 eBPF 进行安全审计、数据包处理、实时性能监控以及优化其庞大基础设施的 CPU 调度。</li>
<li><strong>Netflix</strong>:利用 eBPF 进行网络流量分析,确保流媒体服务的高可用性和性能。</li>
<li><strong>Android</strong>:应用 eBPF 优化网络使用、功耗和资源分配,提升数百万设备的性能和电池寿命。</li>
<li><strong>S&amp;P Global</strong>:通过 <strong>Cilium</strong> 使用 eBPF 管理跨多个云和本地系统的网络,确保可扩展性和安全性。</li>
<li><strong>Shopify</strong>:与 <strong>Falco</strong> 一起实施 eBPF 进行入侵检测,增强其电子商务平台的安全性。</li>
<li><strong>Cloudflare</strong>:使用 eBPF 进行网络可观测性、安全监控和性能优化,保护全球数百万网站。</li>
</ul>
<p>eBPF 能够动态调整系统行为并扩展到用户空间使其成为现代计算不可或缺的技术。无论是优化网络流量、提升安全性还是增强系统性能eBPF 都能帮助开发者高效、安全地应对实时需求。</p>
<p>除了其内核模式运行时eBPF 还可以扩展到用户空间。例如,<a href="https://github.com/eunomia-bpf/bpftime">bpftime</a> 是一个用户空间 eBPF 运行时,允许在用户空间应用中进行高性能追踪、性能分析和插件支持。这种 eBPF 向用户空间的扩展有助于在各种超越内核级任务的用例中提高灵活性和性能。</p>
<h3 id="未来ebpf-的扩展潜力"><a class="header" href="#未来ebpf-的扩展潜力">未来eBPF 的扩展潜力</a></h3>
<p>展望未来,预计 eBPF 将成为操作系统更为重要的一部分。重点将放在提升其灵活性、模块化和易用性上,使其能够应用于更广泛的场景。内存管理、并发机制的创新以及与用户空间应用的更好集成已在路上。已经有项目在编译 Linux 内核的关键部分到 BPF 指令集,这可能彻底改变内核开发和分析的方式。</p>
<p>动态栈、更好的用户空间可观测性工具(例如快速 Uprobes 和特定语言的栈行走器)以及更安全的程序终止机制等进展将继续增强 eBPF 的可靠性并扩展其使用场景。此外,新工具和库将简化 eBPF 开发,降低内核和应用开发者的入门门槛。</p>
<h2 id="开始学习教程"><a class="header" href="#开始学习教程">开始学习教程</a></h2>
<p>本教程提供实用的 eBPF 开发实践,涵盖从初级到高级的主题。我们专注于在可观测性、网络和安全等领域的动手示例,使用 <code>libbpf</code><code>libbpf-rs</code><code>eunomia-bpf</code> 等框架,并提供 C、Go 和 Rust 的示例。</p>
<h3 id="本教程适合谁"><a class="header" href="#本教程适合谁">本教程适合谁?</a></h3>
<ul>
<li><strong>开发者</strong> 希望实现自定义内核解决方案。</li>
<li><strong>系统管理员</strong> 旨在提升性能和安全性。</li>
<li><strong>技术爱好者</strong> 探索前沿的内核技术。</li>
</ul>
<h3 id="你将学到什么"><a class="header" href="#你将学到什么">你将学到什么?</a></h3>
<ul>
<li><strong>核心概念</strong>eBPF 基础知识及其与 Linux 内核的集成。</li>
<li><strong>实用技能</strong>:编写和部署 eBPF 程序。</li>
<li><strong>高级主题</strong>:探索 eBPF 在安全、追踪和未来创新方面的应用。</li>
</ul>
<hr />
<h2 id="目录"><a class="header" href="#目录">目录</a></h2>
<ol>
<li>
<p><strong>eBPF 简介</strong><br />
基本概念和入门所需的工具。</p>
</li>
<li>
<p><strong>初学者示例</strong><br />
简单的程序如“Hello World”及使用 kprobe 和 uprobe 进行基础追踪。</p>
</li>
<li>
<p><strong>可观测性</strong><br />
侧重于使用 eBPF 监控网络流量、文件操作和进程行为的示例。</p>
</li>
<li>
<p><strong>网络</strong><br />
侧重于修改和优化网络流量的示例,如 XDP、TC 和 socket。</p>
</li>
<li>
<p><strong>安全</strong><br />
用于隐藏进程和文件、发送信号杀死进程以及跟踪进程事件以增强安全性的程序。</p>
</li>
<li>
<p><strong>高级用例</strong><br />
涉及性能分析、调度器优化和用户空间 eBPF如 bpftime的复杂示例。</p>
</li>
<li>
<p><strong>深入主题</strong><br />
探索 eBPF 在 Android 上的应用、使用 eBPF 进行网络加速以及通过系统调用修改来保护系统。</p>
</li>
</ol>
<h2 id="如何使用-ebpf-编程"><a class="header" href="#如何使用-ebpf-编程">如何使用 eBPF 编程</a></h2>
<p>从头编写 eBPF 程序可能较为复杂。为简化这一过程LLVM 于 2015 年引入了将高级语言代码编译为 eBPF 字节码的能力。自那时起eBPF 社区构建了像 <code>libbpf</code> 这样的库来管理这些程序。这些库帮助将 eBPF 字节码加载到内核中并执行基本任务。Linux 内核源代码中 <code>samples/bpf/</code> 目录包含了众多 eBPF 示例。</p>
<p>典型的 eBPF 程序包含两个部分:内核空间代码(<code>*_kern.c</code>)和用户空间代码(<code>*_user.c</code>)。内核空间代码定义逻辑,而用户空间代码负责加载和与内核交互。然而,像 <code>libbpf-bootstrap</code> 和 Go eBPF 库这样的工具简化了这一过程,允许一次性编译和更容易的开发。</p>
<h3 id="ebpf-开发工具"><a class="header" href="#ebpf-开发工具">eBPF 开发工具</a></h3>
<ul>
<li><strong>BCC</strong>:一个基于 Python 的工具链,简化了 eBPF 程序的编写、编译和加载。它提供了许多预构建的追踪工具,但在依赖和兼容性方面存在一些限制。</li>
<li><strong>eBPF Go 库</strong>:一个 Go 库,解耦了获取 eBPF 字节码的过程与加载和管理 eBPF 程序的过程。</li>
<li><strong>libbpf-bootstrap</strong>:基于 <code>libbpf</code> 的现代脚手架,提供了高效的工作流用于编写 eBPF 程序,提供简单的一次性编译过程以生成可重用的字节码。</li>
<li><strong>eunomia-bpf</strong>:一个用于编写仅包含内核空间代码的 eBPF 程序的工具链。它通过动态加载 eBPF 程序简化了 eBPF 程序的开发。</li>
</ul>
<p>这些工具有助于减少开发 eBPF 程序的复杂性,使开发者更容易优化系统性能、安全性和可观测性。</p>
<h2 id="学习-ebpf-开发的一些技巧"><a class="header" href="#学习-ebpf-开发的一些技巧">学习 eBPF 开发的一些技巧</a></h2>
<p>本文不会提供更详细的 eBPF 原理介绍,但以下是一个学习计划和参考资料,可能对您有帮助:</p>
<h3 id="ebpf-简介5-7-小时"><a class="header" href="#ebpf-简介5-7-小时">eBPF 简介5-7 小时)</a></h3>
<ul>
<li>使用 Google 或其他搜索引擎搜索eBPF</li>
<li>询问类似 ChatGPT 的工具:什么是 eBPF</li>
</ul>
<p>推荐:</p>
<ul>
<li>阅读 ebpf 简介<a href="https://ebpf.io/">https://ebpf.io/</a> 30min</li>
<li>简要了解一下 ebpf 内核相关文档:<a href="https://prototype-kernel.readthedocs.io/en/latest/bpf/">https://prototype-kernel.readthedocs.io/en/latest/bpf/</a> 知道有问题去哪里查询30min</li>
<li>阅读 ebpf 中文入门指南:<a href="https://www.ebpf.top/post/ebpf_intro">https://www.ebpf.top/post/ebpf_intro</a> 1h</li>
<li>有大量的参考资料:<a href="https://github.com/zoidbergwill/awesome-ebpf">https://github.com/zoidbergwill/awesome-ebpf</a> 2-3h</li>
<li>可以选自己感兴趣的 PPT 翻一翻:<a href="https://github.com/gojue/ebpf-slide">https://github.com/gojue/ebpf-slide</a> 1-2h</li>
<li>阅读 eBPF 介绍<a href="https://ebpf.io/">https://ebpf.io/</a>30 分钟</li>
<li>简要了解 eBPF 内核相关文档:<a href="https://docs.ebpf.io/">https://docs.ebpf.io/</a>了解技术细节的查询来源30 分钟</li>
</ul>
<p>回答三个问题:</p>
<ol>
<li>了解 eBPF 是什么东西?为啥要有这个玩意,不能用内核模块?</li>
<li>它有什么功能?在 Linux 内核里面完成哪些事情?有哪些 eBPF 程序的类型和 helper不需要知道全部,但需要知道哪里找)?</li>
<li>能拿来做什么?比如说在哪些场景中进行运用?网络、安全、可观测性?</li>
<li>了解 eBPF 是什么?我们为什么需要它?难道不能使用内核模块</li>
<li>它有哪些功能?在 Linux 内核中能做什么eBPF 程序和助手函数有哪些类型(不需要全部了解,但需要知道哪里找)?</li>
<li>它能用于哪些场景?例如,可以在哪些情况下使用?网络、安全、可观测性?</li>
</ol>
<h3 id="解如何开发-ebpf-程序10-15h"><a class="header" href="#解如何开发-ebpf-程序10-15h">解如何开发 eBPF 程序10-15h</a></h3>
<p>了解并尝试一下 eBPF 开发框架:</p>
<h3 id="解如何开发-ebpf-程序10-15-小时"><a class="header" href="#解如何开发-ebpf-程序10-15-小时">解如何开发 eBPF 程序10-15 小时</a></h3>
<p>了解并尝试 eBPF 开发框架:</p>
<ul>
<li>bpftrace 教程对于最简单的应用来说bpftrace 可能是最方便的<a href="https://eunomia.dev/zh/tutorials/bpftrace-tutorial/">https://eunomia.dev/zh/tutorials/bpftrace-tutorial/</a> 试试1h</li>
<li>BCC 开发各类小工具的例<a href="https://github.com/iovisor/bcc/blob/master/docs/tutorial_bcc_python_developer.md">https://github.com/iovisor/bcc/blob/master/docs/tutorial_bcc_python_developer.md</a> (跑一遍3-4h</li>
<li>libbpf 的一些例<a href="https://github.com/libbpf/libbpf-bootstrap">https://github.com/libbpf/libbpf-bootstrap</a> (选感兴趣的运行一下,并阅读一下源代码2h</li>
<li>基于 C 语言 libbpf, Go 语言或者 Rust 语言和 eunomia-bpf 的教程:<a href="https://github.com/eunomia-bpf/bpf-developer-tutorial">https://github.com/eunomia-bpf/bpf-developer-tutorial</a> (阅读 1-20 部分3-8h</li>
<li>bpftrace 教程:<a href="https://eunomia.dev/tutorials/bpftrace-tutorial/">https://eunomia.dev/tutorials/bpftrace-tutorial/</a>尝试1 小时</li>
<li>使用 BCC 开发各工具的例:<a href="https://github.com/iovisor/bcc/blob/master/docs/tutorial_bcc_python_developer.md">https://github.com/iovisor/bcc/blob/master/docs/tutorial_bcc_python_developer.md</a>(运行3-4 小时</li>
<li>libbpf 的一些例:<a href="https://github.com/libbpf/libbpf-bootstrap">https://github.com/libbpf/libbpf-bootstrap</a>(运行任何有趣的示例并阅读源代码2 小时</li>
<li>教程:<a href="https://github.com/eunomia-bpf/bpf-developer-tutorial">https://github.com/eunomia-bpf/bpf-developer-tutorial</a>(阅读 1-10 部分3-4 小时</li>
</ul>
<p>有任何问题或者想了解的东西,不管是不是和本项目相关,都可以在本项目的 discussions 里面开始讨论。</p>
<p>回答一些问题并且进行一些尝试2-5h</p>
<p>其他开发框架Go 或 Rust 语言请自行搜索和尝试0-2 小时)</p>
<p>如果有问题或想了解的内容,无论是否与本项目相关,都可以在该项目的讨论区开始讨论。</p>
<p>回答一些问题并尝试一些实验2-5 小时):</p>
<ol>
<li>如何开发一个最简单的 eBPF 程序?</li>
<li>如何用 eBPF 追踪一个内核功能或函数?有很多方法,举出对应的代码;</li>
<li>有哪些方案能通过用户态和内核态通信?如何从用户态向内核态传送信息?如何从内核态向用户态传递信息?举出代码示例;</li>
<li>编写一个你自己的 eBPF 程序实现个功能;</li>
<li>eBPF 程序的整个生命周期里面,分别在用户态和内核态做了哪些事情</li>
<li>如何开发最简单的 eBPF 程序?</li>
<li>如何使用 eBPF 追踪内核功能或函数?有很多方法,提供相应的代码示例</li>
<li>用户模式和内核模式之间的通信解决方案有哪些?如何将信息从用户模式发送到内核模式?如何将信息从内核模式传递到用户模式?提供代码示例;</li>
<li>编写自己的 eBPF 程序实现个功能;</li>
<li>eBPF 程序的整个生命周期中,用户模式和内核模式分别做了什么</li>
</ol>
<h2 id="3-如何使用-ebpf-编程"><a class="header" href="#3-如何使用-ebpf-编程">3. 如何使用 eBPF 编程</a></h2>
<p>原始的 eBPF 程序编写是非常繁琐和困难的。为了改变这一现状llvm 于 2015 年推出了可以将由高级语言编写的代码编译为 eBPF 字节码的功能同时eBPF 社区将 <code>bpf()</code> 等原始的系统调用进行了初步地封装,给出了 <code>libbpf</code> 库。这些库会包含将字节码加载到内核中的函数以及一些其他的关键函数。在 Linux 的源码包的 <code>samples/bpf/</code> 目录下,有大量 Linux 提供的基于 <code>libbpf</code> 的 eBPF 样例代码。</p>
<p>一个典型的基于 <code>libbpf</code> 的 eBPF 程序具有 <code>*_kern.c</code><code>*_user.c</code> 两个文件,<code>*_kern.c</code> 中书写在内核中的挂载点以及处理函数,<code>*_user.c</code> 中书写用户态代码,完成内核态代码注入以及与用户交互的各种任务。 更为详细的教程可以参考<a href="https://www.bilibili.com/video/BV1f54y1h74r?spm_id_from=333.999.0.0">该视频</a>。然而由于该方法仍然较难理解且入门存在一定的难度因此现阶段的eBPF程序开发大多基于一些工具比如</p>
<ul>
<li>BCC</li>
<li>BPFtrace</li>
<li>libbpf-bootstrap</li>
<li>Go eBPF library</li>
</ul>
<p>以及还有比较新的工具,例如 <code>eunomia-bpf</code>.</p>
<h2 id="编写-ebpf-程序"><a class="header" href="#编写-ebpf-程序">编写 eBPF 程序</a></h2>
<p>eBPF 程序由内核态部分和用户态部分构成。内核态部分包含程序的实际逻辑,用户态部分负责加载和管理内核态部分。使用 eunomia-bpf 开发工具,只需编写内核态部分的代码。</p>
<p>内核态部分的代码需要符合 eBPF 的语法和指令集。eBPF 程序主要由若干个函数组成,每个函数都有其特定的作用。可以使用的函数类型包括:</p>
<ul>
<li>kprobe插探函数在指定的内核函数前或后执行。</li>
<li>tracepoint跟踪点函数在指定的内核跟踪点处执行。</li>
<li>raw_tracepoint原始跟踪点函数在指定的内核原始跟踪点处执行。</li>
<li>xdp网络数据处理函数拦截和处理网络数据包。</li>
<li>perf_event性能事件函数用于处理内核性能事件。</li>
<li>kretprobe函数返回插探函数在指定的内核函数返回时执行。</li>
<li>tracepoint_return跟踪点函数返回在指定的内核跟踪点返回时执行。</li>
<li>raw_tracepoint_return原始跟踪点函数返回在指定的内核原始跟踪</li>
</ul>
<h3 id="bcc"><a class="header" href="#bcc">BCC</a></h3>
<p>BCC 全称为 BPF Compiler Collection该项目是一个 python 库,
包含了完整的编写、编译、和加载 BPF 程序的工具链,以及用于调试和诊断性能问题的工具。</p>
<p>自 2015 年发布以来BCC 经过上百位贡献者地不断完善后,目前已经包含了大量随时可用的跟踪工具。<a href="https://github.com/iovisor/bcc/blob/master/docs/tutorial.md">其官方项目库</a>
提供了一个方便上手的教程,用户可以快速地根据教程完成 BCC 入门工作。</p>
<p>用户可以在 BCC 上使用 Python、Lua 等高级语言进行编程。
相较于使用 C 语言直接编程,这些高级语言具有极大的便捷性,用户只需要使用 C 来设计内核中的
BPF 程序,其余包括编译、解析、加载等工作在内,均可由 BCC 完成。</p>
<p>然而使用 BCC 存在一个缺点便是在于其兼容性并不好。基于 BCC 的
eBPF 程序每次执行时候都需要进行编译,编译则需要用户配置相关的头文件和对应实现。在实际应用中,
相信大家也会有体会,编译依赖问题是一个很棘手的问题。也正是因此,在本项目的开发中我们放弃了 BCC
选择了可以做到一次编译-多次运行的 libbpf-bootstrap 工具。</p>
<h3 id="ebpf-go-library"><a class="header" href="#ebpf-go-library">eBPF Go library</a></h3>
<p>eBPF Go 库提供了一个通用的 eBPF 库,它解耦了获取 eBPF 字节码的过程和 eBPF 程序的加载和管理,并实现了类似 libbpf 一样的 CO- 功能。eBPF 程序通常是通过编写高级语言创建的,然后使用 clang/LLVM 编译器编译为 eBPF 字节码。</p>
<h3 id="libbpf"><a class="header" href="#libbpf">libbpf</a></h3>
<p><code>libbpf-bootstrap</code> 是一个基于 <code>libbpf</code> 库的 BPF 开发脚手架,从其
<a href="https://github.com/libbpf/libbpf-bootstrap">github</a> 上可以得到其源码。</p>
<p><code>libbpf-bootstrap</code> 综合了 BPF 社区过去多年的实践,为开发者提了一个现代化的、便捷的工作流,实
现了一次编译,重复使用的目的。</p>
<p>基于 <code>libbpf-bootstrap</code> 的 BPF 程序对于源文件有一定的命名规则,
用于生成内核态字节码的 bpf 文件以 <code>.bpf.c</code> 结尾,用户态加载字节码的文件以 <code>.c</code> 结尾,且这两个文件的
前缀必须相同。</p>
<p>基于 <code>libbpf-bootstrap</code> 的 BPF 程序在编译时会先将 <code>*.bpf.c</code> 文件编译为
对应的 <code>.o</code> 文件,然后根据此文件生成 <code>skeleton</code> 文件,即 <code>*.skel.h</code>,这个文件会包含内核态中定义的一些
数据结构,以及用于装载内核态代码的关键函数。在用户态代码 <code>include</code> 此文件之后调用对应的装载函数即可将
字节码装载到内核中。同样的,<code>libbpf-bootstrap</code> 也有非常完备的入门教程,用户可以在<a href="https://nakryiko.com/posts/libbpf-bootstrap/">该处</a>
得到详细的入门操作介绍。</p>
<h3 id="eunomia-bpf"><a class="header" href="#eunomia-bpf">eunomia-bpf</a></h3>
<p><a href="https://github.com/eunomia-bpf/eunomia-bpf">eunomia-bpf</a> 是一个开源的 eBPF 动态加载运行时和开发工具链,是为了简化 eBPF 程序的开发、构建、分发、运行而设计的,基于 libbpf 的 CO-RE 轻量级开发框架。</p>
<p>使用 eunomia-bpf ,可以:</p>
<ul>
<li>在编写 eBPF 程序或工具时只编写内核态代码,自动获取内核态导出信息,并作为模块动态加载;</li>
<li>eunomia-bpf 可以将预编译的 eBPF 程序打包为通用的 JSON 或 WASM 模块,跨架构和内核版本进行分发,无需重新编译即可动态加载运行。</li>
</ul>
<p>eunomia-bpf 由一个编译工具链和一个运行时库组成, 对比传统的 BCC、原生 libbpf 等框架,简化了 eBPF 程序的开发流程,在大多数时候只需编写内核态代码,即可轻松构建、打包、发布完整的 eBPF 应用。</p>
<blockquote>
<ul>
<li>eunomia-bpf 项目 Github 地址: <a href="https://github.com/eunomia-bpf/eunomia-bpf">https://github.com/eunomia-bpf/eunomia-bpf</a></li>
<li>gitee 镜像: <a href="https://gitee.com/anolis/eunomia">https://gitee.com/anolis/eunomia</a></li>
</ul>
</blockquote>
<h2 id="参考资料"><a class="header" href="#参考资料">参考资料</a></h2>
<ul>
<li>eBPF 介绍:<a href="https://ebpf.io/">https://ebpf.io/</a></li>
<li>BPF Compiler Collection (BCC)<a href="https://github.com/iovisor/bcc">https://github.com/iovisor/bcc</a></li>
<li>BPF 编译器集合(BCC<a href="https://github.com/iovisor/bcc">https://github.com/iovisor/bcc</a></li>
<li>eunomia-bpf<a href="https://github.com/eunomia-bpf/eunomia-bpf">https://github.com/eunomia-bpf/eunomia-bpf</a></li>
</ul>
<p>您还可以访问我们的教程代码仓库 <a href="https://github.com/eunomia-bpf/bpf-developer-tutorial">https://github.com/eunomia-bpf/bpf-developer-tutorial</a> 或网站 <a href="https://eunomia.dev/zh/tutorials/">https://eunomia.dev/zh/tutorials/</a> 获取更多示例和完整的教程源代码。我们继续分享更多关 eBPF 开发实践的内容,帮助您更好地理解和掌握 eBPF 技术。</p>
<blockquote>
<p>原文地址:<a href="https://eunomia.dev/zh/tutorials/0-introduce/">https://eunomia.dev/zh/tutorials/0-introduce/</a> 转载请注明</p>
</blockquote>
<p>您还可以访问我们的教程代码仓库 <a href="https://github.com/eunomia-bpf/bpf-developer-tutorial">https://github.com/eunomia-bpf/bpf-developer-tutorial</a> 或网站 <a href="https://eunomia.dev/tutorials/">https://eunomia.dev/tutorials/</a> 获取更多示例和完整的教程源代码。所有内容均为开源。我们继续分享更多关 eBPF 开发实践的内容,帮助您更好地理解和掌握 eBPF 技术。</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="ebpf-入门开发实践教程一hello-world基本框架和开发流程"><a class="header" href="#ebpf-入门开发实践教程一hello-world基本框架和开发流程">eBPF 入门开发实践教程一Hello World基本框架和开发流程</a></h1>
<p>在本篇博客中我们将深入探讨eBPFExtended Berkeley Packet Filter的基本框架和开发流程。eBPF是一种在Linux内核上运行的强大网络和性能分析工具它为开发者提供了在内核运行时动态加载、更新和运行用户定义代码的能力。这使得开发者可以实现高效、安全的内核级别的网络监控、性能分析和故障排查等功能。</p>
<p>本文是eBPF入门开发实践教程的第二篇我们将重点关注如何编写一个简单的eBPF程序并通过实际例子演示整个开发流程。在阅读本教程之前建议您先学习第一篇教程以便对eBPF的基本概念有个大致的了解。</p>
@@ -4523,7 +4542,7 @@ ndlock,lockdown,yama,integrity,apparmor
<pre><code class="language-conf">GRUB_CMDLINE_LINUX="lsm=ndlock,lockdown,yama,integrity,apparmor,bpf"
</code></pre>
<p>并通过 <code>update-grub2</code> 命令更新 grub 配置(不同系统的对应命令可能不同),然后重启系统。</p>
<h2 id="编写-ebpf-程序-1"><a class="header" href="#编写-ebpf-程序-1">编写 eBPF 程序</a></h2>
<h2 id="编写-ebpf-程序"><a class="header" href="#编写-ebpf-程序">编写 eBPF 程序</a></h2>
<pre><code class="language-C">// lsm-connect.bpf.c
#include "vmlinux.h"
#include &lt;bpf/bpf_core_read.h&gt;
@@ -4629,7 +4648,7 @@ Retrying.
<p>从协议栈上看tc 位于链路层,其所在位置已经完成了 sk_buff 的分配,要晚于 xdp。为了实现对数据包发送和接收的控制tc 使用队列结构来临时保存并组织数据包,在 tc 子系统中对应的数据结构和算法控制机制被抽象为 qdiscQueueing discipline其对外暴露数据包入队和出队的两个回调接口并在内部隐藏排队算法实现。在 qdisc 中我们可以基于 filter 和 class 实现复杂的树形结构,其中 filter 被挂载到 qdisc 或 class 上用于实现具体的过滤逻辑,返回值决定了该数据包是否属于特定 class。</p>
<p>当数据包到达顶层 qdisc 时,其入队接口被调用,其上挂载的 filter 被依次执行直到一个 filter 匹配成功;此后数据包被送入该 filter 指向的 class进入该 class 配置的 qdisc 处理流程中。tc 框架提供了所谓 classifier-action 机制,即在数据包匹配到特定 filter 时执行该 filter 所挂载的 action 对数据包进行处理,实现了完整的数据包分类和处理机制。</p>
<p>现有的 tc 为 eBPF 提供了 direct-action 模式,它使得一个作为 filter 加载的 eBPF 程序可以返回像 <code>TC_ACT_OK</code> 等 tc action 的返回值,而不是像传统的 filter 那样仅仅返回一个 classid 并把对数据包的处理交给 action 模块。现在eBPF 程序可以被挂载到特定的 qdisc 上,并完成对数据包的分类和处理动作。</p>
<h2 id="编写-ebpf-程序-2"><a class="header" href="#编写-ebpf-程序-2">编写 eBPF 程序</a></h2>
<h2 id="编写-ebpf-程序-1"><a class="header" href="#编写-ebpf-程序-1">编写 eBPF 程序</a></h2>
<pre><code class="language-c">#include &lt;vmlinux.h&gt;
#include &lt;bpf/bpf_endian.h&gt;
#include &lt;bpf/bpf_helpers.h&gt;
@@ -4774,7 +4793,7 @@ Packing ebpf object and config into package.json...
<p><strong>资源效率</strong>XDP 不需要像 DPDK 等用户空间解决方案那样将整个 CPU 核心专用于数据包处理,因此它是高性能网络的更高效选择。</p>
</li>
</ul>
<h2 id="编写-ebpf-程序-3"><a class="header" href="#编写-ebpf-程序-3">编写 eBPF 程序</a></h2>
<h2 id="编写-ebpf-程序-2"><a class="header" href="#编写-ebpf-程序-2">编写 eBPF 程序</a></h2>
<pre><code class="language-C">#include "vmlinux.h"
#include &lt;bpf/bpf_helpers.h&gt;
@@ -6820,7 +6839,7 @@ sudo ls -l /sys/fs/bpf/textreplace
<p>郑昱笙</p>
<p>扩展伯克利数据包过滤器eBPF代表了我们与现代操作系统交互和扩展其能力方式的重大演变。作为一种强大的技术它使得Linux内核能够响应事件运行沙盒程序eBPF已成为系统可观察性、网络和安全特性的基石。</p>
<p>然而像任何与内核紧密接口的系统一样eBPF 运行时本身的安全性至关重要。在这篇博客中,我们将深入探讨常被忽视的 eBPF 安全性问题,探索旨在保护 eBPF 的机制本身如何被加固。我们将解析 eBPF 验证器的作用,审视当前的访问控制模型,并调查研究中的潜在改进机会。</p>
<h2 id="目录"><a class="header" href="#目录">目录</a></h2>
<h2 id="目录-1"><a class="header" href="#目录-1">目录</a></h2>
<!-- TOC -->
<ul>
<li><a href="18-further-reading/ebpf-security.zh.html#ebpf-%E8%BF%90%E8%A1%8C%E6%97%B6%E5%AE%89%E5%85%A8%E6%80%A7%E9%9D%A2%E4%B8%B4%E7%9A%84%E6%8C%91%E6%88%98%E4%B8%8E%E5%89%8D%E6%B2%BF%E5%88%9B%E6%96%B0">eBPF 运行时安全性:面临的挑战与前沿创新</a>
@@ -8483,7 +8502,7 @@ The list of subcommands supported in your kernel can be found in file
</div><div style="break-before: page; page-break-before: always;"></div><h1 id="bcc-参考指南"><a class="header" href="#bcc-参考指南">bcc 参考指南</a></h1>
<p>用于搜索 (Ctrl-F) 和参考。如需教程,请从 <a href="bcc-documents/tutorial.html">tutorial.md</a> 开始。</p>
<p>该指南尚未完成。如果感觉有遗漏的内容,请查看 bcc 和内核源码。如果确认确实有遗漏,请发送拉取请求进行修复,并协助所有人。</p>
<h2 id="目录-1"><a class="header" href="#目录-1">目录</a></h2>
<h2 id="目录-2"><a class="header" href="#目录-2">目录</a></h2>
<ul>
<li><a href="bcc-documents/reference_guide.html#bcc-%E5%8F%82%E8%80%83%E6%8C%87%E5%8D%97">bcc 参考指南</a>
<ul>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long