当前位置: 首页 > news >正文

扩展:操作系统之高性能网络计算

穿越性能边界:Linux Kernel 网络发包技术的演进与对比

在现代计算环境中,网络性能往往是决定系统整体吞吐量和响应速度的关键因素。尤其是在需要处理海量并发连接、进行高速数据传输(如高性能计算、网络功能虚拟化 NFV、金融交易、大数据处理)的场景下,如何高效地将数据从应用程序推送到网络介质,是摆在开发者面前的重要挑战。

Linux 内核提供了多种不同的机制和接口来实现数据包的发送。这些技术在易用性、灵活性、以及最关键的——数据包发送速度上有着显著的差异。本文将按照大致的数据包发送速度从低到高的顺序,介绍 Linux 下主要的网络发包技术,并探讨它们背后的原理和适用场景。

在此之前,我们先简要了解一下两个与高性能网络密切相关的基础技术:eBPF 和 XDP。

基础技术:eBPF 与 XDP

eBPF (Extended Berkeley Packet Filter)

eBPF 是一种在 Linux 内核中安全执行自定义程序的技术。它将内核变成了一个可编程的平台,而无需修改内核源代码或加载内核模块。开发者可以使用一个受限的 C 语言子集编写程序,编译成 BPF 字节码,然后加载到内核。内核的验证器会严格检查程序的安全性,防止其崩溃内核或访问非法内存。通过 JIT (Just-In-Time) 编译器,BPF 字节码可以被编译成高效的本地机器码执行。

eBPF 程序可以附加到内核中的各种事件点 (attachment points),包括系统调用、内核函数、用户空间函数、跟踪点以及网络事件。这使得在不牺牲性能和安全性的前提下,对内核的行为进行深度观察、定制和控制成为可能。eBPF 是许多现代 Linux 高性能网络和可观测性工具的基石。

XDP (eXpress Data Path)

XDP 是 Linux 内核中基于 eBPF 实现的一种高性能网络数据路径。它是一个特定的 eBPF 附加点,位于网络驱动程序接收数据包的最早阶段,即在数据包刚从网卡 DMA 到内核内存后,但在传统的网络协议栈处理(如创建 sk_buff,进入 IP 层、TCP/UDP 层)之前或同时

通过将一个 XDP eBPF 程序附加到网卡接口上,可以在数据包进入主网络栈之前对其进行极快速的处理。XDP 程序对每个数据包执行后,会返回一个“判决”(Verdict),决定数据包的命运:

  • XDP_DROP: 直接丢弃数据包。这是最快的丢弃方式。
  • XDP_PASS: 允许数据包继续进入正常的网络协议栈进行后续处理。
  • XDP_TX: 将数据包从接收它的同一个网卡发送出去。这用于实现高性能的回显、流量镜像或快速转发。
  • XDP_REDIRECT: 将数据包重定向到另一个网络接口,或者重定向到一个 AF_XDP Socket

XDP 的速度优势来自于它在数据包处理流程的极早期运行,避免了创建 sk_buff 的开销以及数据包在复杂协议栈中层层传递和处理的成本。

Linux 网络发包技术:速度从低到高

接下来,我们将按照大致的发包性能从低到高,介绍主要的 Linux 发包技术。

1. 标准 Socket API (SOCK_STREAM, SOCK_DGRAM)

  • 描述: 这是最普遍、最易用、最“高级”的网络接口。应用程序通过标准的 POSIX Socket API (如 socket(), connect(), bind(), send(), sendto(), write()) 进行网络通信。
  • 工作原理: 当应用程序调用发送函数时,数据从用户空间的缓冲区通过系统调用复制到内核空间的 sk_buff。然后 sk_buff 会沿着完整的内核网络协议栈向下传递:经过传输层(TCP/UDP 分段/封装)、网络层(IP 路由、分片、地址查找)、数据链路层(添加 Ethernet 头部、ARP 解析)以及流量控制等。最终,数据包被交给网卡驱动程序,放入硬件的发送队列,由硬件发送出去。
  • 性能特点:
    • 速度: 相对较低。主要瓶颈在于:
      • 系统调用开销: 每次发送数据都需要进入内核。
      • 内存复制: 数据需要从用户空间复制到内核空间。
      • 协议栈开销: 数据包需要经过协议栈的多层处理,涉及锁定和状态管理。
    • 易用性: 最高。API 简单,无需关心底层协议细节。
    • 功能: 功能最完善,支持 TCP/UDP 的所有特性、路由、防火墙、NAT 等。
  • 典型用途: 绝大多数应用程序(Web 服务器/客户端, SSH, 文件传输等),对性能要求不极致的场景。

2. Raw Sockets (SOCK_RAW, AF_INET/AF_INET6)

  • 描述: 允许应用程序在 IP 层直接发送和接收数据包。用户空间需要自己构建 IP 头部以及上层协议(TCP/UDP 等)的头部。
  • 工作原理: 用户空间准备好包含 IP 头部及后续数据的原始字节序列,通过 send/sendto 系统调用发送。内核接收到这些数据后,会跳过标准的传输层处理,直接从 IP 层开始向下处理:进行路由查找、Netfilter 过滤、添加数据链路层头部(如 Ethernet 头部)并处理 ARP,然后将数据包交给驱动程序发送。
  • 性能特点:
    • 速度: 比标准 Socket 略快。绕过了传输层处理的开销。但仍然存在用户空间到内核空间的内存复制和系统调用开销。对于大量小包的发送,性能提升不明显。
    • 易用性: 较低。需要手动构建 IP 头部及上层协议头部。
    • 功能: 可以实现自定义的 IP 层协议或报文,但无法利用标准 TCP/UDP 的所有高级特性。
  • 典型用途: Ping、Traceroute、自定义 IP 协议实现、网络诊断工具。

3. AF_PACKET (Traditional AF_PACKET, SOCK_RAW/SOCK_DGRAM)

  • 描述: 允许应用程序在数据链路层(L2)直接发送和接收数据包。用户空间需要构建包括 Ethernet 头部在内的完整数据帧。
  • 工作原理: 用户空间准备好完整的原始数据帧(例如 Ethernet + IP + TCP/UDP + 数据),通过 send/sendto 发送。内核接收后,会跳过 IP、TCP、UDP 等所有高层协议栈的处理,只进行最少的必要处理(如将帧添加到设备的发送队列),然后由网卡驱动发送出去。
  • 性能特点:
    • 速度: 比 Raw Socket 快。因为它绕过了整个 IP 层及以上协议栈的处理。但瓶颈依然是用户空间到内核空间的内存复制和系统调用开销。
    • 易用性: 较低。需要手动构建完整的 L2 及以上所有头部。
    • 功能: 可以完全控制 L2 帧的结构。
  • 典型用途: tcpdump 等抓包工具、自定义桥接/隧道实现、需要直接操作 L2 帧的应用程序。

4. AF_PACKET (TPACKET Variants: TPACKET_V1, TPACKET_V2, TPACKET_V3)

  • 描述: 这是 AF_PACKET 的一个优化版本,利用内存映射 (mmap) 来减少数据在用户空间和内核空间之间的复制。它通过 setsockopt 设置 PACKET_RX_RINGPACKET_TX_RING 来启用。
  • 工作原理: 用户空间和内核通过 mmap 系统调用共享一块内存区域,这块内存被组织成环形缓冲区(Packet Ring)。用户空间将要发送的数据帧直接写入这块共享内存的 TX Ring Buffer 中的缓冲区。然后通过一个轻量级的系统调用(例如 sendto 或特殊的 sendmmsg) 通知内核有数据待发送。内核的驱动可以直接从共享内存的环形缓冲区中获取数据帧并发送,避免了传统 send/write 的数据复制
  • 性能特点:
    • 速度: 显著快于传统的 AF_PACKET。通过零拷贝或减少拷贝,极大地降低了每包发送的 CPU 开销和延迟,提高了吞吐量。系统调用开销依然存在,但由于批量提交(如 sendmmsg)可以有效降低单包的系统调用成本。
    • 易用性: 较低。API 比标准 Socket 复杂得多,需要管理共享内存环形缓冲区和缓冲区状态。
  • 典型用途: 高性能抓包工具、用户空间的软件交换机/路由器、需要高性能 L2 帧处理且对延迟敏感的应用。在 AF_XDP 出现之前,这是 Linux 上实现高性能用户空间网络应用的常见选择。

5. AF_XDP (AF_XDP, SOCK_RAW)

  • 描述: AF_XDP 是一种特殊的 Socket 地址族,它结合了 XDP 和 eBPF 技术,为用户空间提供极高性能的数据包收发接口,旨在绕过大部分内核网络协议栈
  • 工作原理:
    • 需要一个支持 XDP 和 AF_XDP 的网卡驱动。
    • 需要一个附加到该网卡接口上的 XDP eBPF 程序,该程序通常用于将数据包重定向 (XDP_REDIRECT) 到 AF_XDP Socket。
    • 用户空间应用程序创建一个 AF_XDP 类型的 Socket,并将其绑定到网卡接口的特定队列上。
    • 用户空间和内核通过 mmap 共享一块巨大的内存区域,称为 UMEM (Userspace Memory)。UMEM 被组织成多个环形缓冲区 (Ring Buffers): Fill Ring, Completion Ring, Tx Ring, Rx Ring。
    • 发送: 用户空间应用程序将要发送的完整原始数据帧(如 Ethernet + IP + UDP + 数据)直接写入 UMEM 中的某个缓冲区。然后将该缓冲区的描述符(偏移量和长度)提交到 Tx Ring。通过一个轻量级的系统调用(或 Poll)通知内核 Tx Ring 有新的发送任务。内核的 XDP 层(或驱动)可以直接从 UMEM 中获取数据并将其放入硬件发送队列发送,完全避免了数据复制。发送完成后,缓冲区的描述符被放回 Completion Ring,用户空间通过 Poll 从 Completion Ring 回收可重用的缓冲区描述符。
  • 性能特点:
    • 速度: 通常是 Linux 内核原生(即不完全绕过内核)用户空间网络技术中最快的。它将包处理推到离硬件最近的 XDP 层,利用零拷贝 UMEM 机制,并通过批量操作和轻量级通知机制,极大地降低了延迟和 CPU 开销,能够处理极高的包率(通常能达到几十 Gbps 或更高)。
    • 易用性: 最低(相对于 Socket API)。API 复杂,需要理解和管理 UMEM 和四种环形缓冲区,需要手动构建完整的 L2-L4 头部,还需要编写或加载一个配套的 BPF 程序。
    • 功能: 绕过大部分内核协议栈,许多高级网络功能(如 TCP 连接管理、复杂路由、高级防火墙规则)需要用户空间自己实现或通过 BPF 程序辅助。
  • 典型用途: 高性能用户空间网络功能 (UNF),如用户空间负载均衡器、高性能转发平面、自定义高性能协议栈、高速数据包采集和分析。

6. Kernel Bypass (DPDK, Netmap, PF_RING ZC等)

  • 描述: 这类技术完全绕过 Linux 内核网络协议栈。它们不是标准的 Socket API,而是通过专用的用户空间库和通常需要特定驱动程序(如 UIO - Userspace I/O, VFIO)或修改过的内核驱动来实现。
  • 工作原理: 用户空间应用程序直接与网卡硬件的 DMA 内存和控制寄存器交互。它们不使用中断,而是使用轮询 (Polling) 方式不断检查网卡的接收和发送队列。所有的网络协议逻辑(L2-L4)都在用户空间的库或应用程序中实现。为了获得独占的控制权和避免竞争,通常需要将网卡或网卡的一部分队列独占地分配给用户空间应用程序。
  • 性能特点:
    • 速度: 通常能达到最高的吞吐量和最低的延迟,接近硬件线速。通过完全绕过内核、零拷贝、使用轮询代替中断,消除了内核协议栈、系统调用、上下文切换、锁竞争等所有开销。
    • 易用性: 非常低。编程模型复杂,需要深入理解底层硬件和驱动细节。轮询模式会占用整个 CPU 核心(如果流量高)。需要特定的硬件和驱动支持。
    • 功能: 所有网络功能(路由、防火墙、协议栈)都需要在用户空间的库中实现。
  • 典型用途: 电信级软件路由器/交换机、高性能网络安全设备、金融高频交易系统、科学计算集群、需要极致网络性能的 NFV 应用。

7. RDMA (Remote Direct Memory Access)

  • 描述: RDMA 与前面几种技术有所不同。它不是通过内核网络栈发送数据包来实现应用程序间通信的通用技术,而是一种允许一台计算机直接访问另一台计算机内存的技术,而无需操作系统和 CPU 的过多干预。它需要专门支持 RDMA 的网卡 (RNIC),如 InfiniBand, RoCE (RDMA over Converged Ethernet), iWARP。
  • 工作原理: 应用程序通过 RDMA API (如 libverbs) 设置内存区域为可远程访问,然后通过 RNIC 发送指令(如 READ, WRITE, SEND)给远程 RNIC。远程 RNIC 直接读写对端内存,数据传输路径绕过了两端的 CPU 和操作系统内核。这是一种零拷贝、低延迟、高带宽的直接内存访问机制。虽然数据最终也是通过网络以包的形式传输,但这些包的生成、处理和投递是由 RNIC 完成的,不经过传统的内核网络栈
  • 性能特点:
    • 速度: 对于特定的应用场景(进程间通信、存储访问),RDMA 提供极低的延迟和极高的带宽,远超基于 TCP/IP 的 Socket 通信。这是因为它完全绕过了操作系统内核、TCP/IP 协议栈以及 CPU 的参与。
    • 易用性: 较低。API 复杂,需要特殊的硬件和配置,编程模型与传统的 Socket 编程差异很大。
    • 功能: 主要用于内存读写和消息传递,不实现完整的通用网络协议栈功能。
  • 典型用途: 高性能计算 (HPC)、大规模数据存储系统 (如 Ceph, Lustre)、数据库集群、分布式缓存系统、需要极低通信延迟和高带宽的场景。

总结与权衡

下表大致总结了这些技术在性能、易用性和复杂性上的权衡:

技术性能 (发包速度)易用性复杂性内存复制内核栈参与程度
标准 Socket非常高多次 (用户->内核->驱动)
Raw Socket较低多次 (用户->内核->驱动)中高
AF_PACKET (Traditional)较低多次 (用户->内核->驱动)中低
AF_PACKET (TPACKET)中高中高减少/零拷贝 (mmap)中低
AF_XDP非常低零拷贝 (UMEM)
Kernel Bypass (DPDK)非常高非常低非常高零拷贝
RDMA极致 (特定场景)非常低非常高零拷贝无 (点对点内存)

选择哪种技术取决于应用程序的具体需求。对于大多数通用应用,标准 Socket API 已经足够且最易于开发和维护。当需要处理更高流量或对延迟有更严格要求时,可以考虑 AF_PACKET 的 TPACKET 或 AF_XDP。而对于需要榨取极致网络性能、可以接受巨大开发复杂性和硬件限制的场景,完全内核旁路技术或 RDMA 可能是必要的。

理解 Linux 网络栈的不同层次及其对应的接口,有助于开发者选择最适合自身需求的工具,从而构建高性能的网络应用程序。



文章转载自:
http://carcinomatous.bdypl.cn
http://canada.bdypl.cn
http://anam.bdypl.cn
http://bullnecked.bdypl.cn
http://amphistylar.bdypl.cn
http://burning.bdypl.cn
http://bejewlled.bdypl.cn
http://captive.bdypl.cn
http://blastoff.bdypl.cn
http://aeroplane.bdypl.cn
http://beidaihe.bdypl.cn
http://charitably.bdypl.cn
http://autocross.bdypl.cn
http://applecart.bdypl.cn
http://capitular.bdypl.cn
http://chalcography.bdypl.cn
http://aeschylus.bdypl.cn
http://binal.bdypl.cn
http://cattail.bdypl.cn
http://boyg.bdypl.cn
http://bimbo.bdypl.cn
http://abluent.bdypl.cn
http://actor.bdypl.cn
http://carucate.bdypl.cn
http://bachelorhood.bdypl.cn
http://chronogram.bdypl.cn
http://anaerobium.bdypl.cn
http://anion.bdypl.cn
http://bemusement.bdypl.cn
http://bestrew.bdypl.cn
http://www.dtcms.com/a/281076.html

相关文章:

  • 使用 mongoimport 导入本地 JSON 文件到 MongoDB 及数据查看指南
  • 微信小程序入门实例_____从零开始 开发一个每天记账的微信小程序
  • Rust语言
  • Isaac Sim仿真赋能机器人工作流,推动具身智能在机器人领域研究
  • 深入解析:磁盘级文件与内存级(被打开)文件的本质区别与联系
  • MySQL锁机制与SQL优化详解
  • Vue 中 effectScope() 的全面解析与实战应用
  • 虚拟机删除操作
  • lanch4j将jar转成exe
  • 文心4.5开源背后的战略棋局:百度为何选择All in开放?
  • Django基础(二)———URL与映射
  • 10 款游戏设计工具深度解析,打造卓越游戏项目
  • 在Autodl服务器中使用VNC建立图形界面
  • MySQL查询今天、昨天、上周、近30天、去年等的数据的方法
  • [锂电池]锂电池入门指南
  • Android 多语言适配(I18n)
  • 逻辑回归案例
  • Prompt提示工程
  • just thinking for vocabulary
  • Visual Prompt Tuning核心思路讲解(个人总结)
  • 《大数据技术原理与应用》实验报告七 熟悉 Spark 初级编程实践
  • 物联网系统中MQTT设备数据的保存方法
  • 了解 Android 内存使用情况 - Google I/O 大会演讲
  • ethers.js-8-bigNmber和callstatic模拟
  • 【Android】日志的使用
  • 《黑马笔记》 --- C++核心编程
  • 10分钟搞定!Chatbox+本地知识库=你的私人语音导师:企业级全栈实现指南
  • etcd压缩历史版本
  • 安装MATLAB流程中遇到的问题
  • wpf Canvas 动态增加右键菜单