零拷贝技术:减少数据复制和上下文切换,提高网络传输效率(下)

简介: 本章节主要讨论了如何通过零拷贝技术来优化文件传输的性能。零拷贝技术主要通过减少用户态和内核态之间的上下文切换次数和数据拷贝次数来提高性能。具体来说,介绍了两种实现零拷贝的方式:mmap + write和sendfile。使用mmap + write可以减少一次数据拷贝过程,而使用sendfile系统调用可以进一步减少系统调用和数据拷贝次数。此外,还介绍了如果网卡支持SG-DMA技术,可以通过DMA将数据直接拷贝到网卡缓冲区,实现真正的零拷贝。通过这些优化方法,可以显著提高文件传输的性能。

前章回顾

在前一章节中,我们了解了DMA技术在文件传输中的重要性,并简要介绍了零拷贝技术。为了提高文件传输的性能,我们需要减少用户态与内核态之间的上下文切换次数以及内存拷贝次数。本章将深入探讨零拷贝技术的优化方法,让我们一起走进零拷贝的优化之路!

如何优化文件传输的性能?

当我们意识到有问题需要进行优化时,我们可以逐个解决问题,例如先减少用户态和内核态的上下文切换次数。

我们知道上下文切换是因为用户空间没有权限操作磁盘或网卡,而只能在虚拟空间上进行。相比之下,内核拥有最高权限,因此操作设备的任务都需要操作系统内核完成。为此,我们需要使用操作系统提供的系统调用函数来通过内核完成这些任务。如果对此还不清楚的小伙伴,可以查看之前章节中单独讲解的内容。

一次系统调用必然会发生两次上下文切换:首先从用户态切换到内核态,当内核执行完任务后,再切换回用户态由进程代码继续执行。

因此,要减少上下文切换的次数,就需要减少系统调用的次数。

另外,我们还可以减少数据拷贝的次数。在之前的分析中,我们发现操作会进行四次数据拷贝,包括两次CPU拷贝和两次DMA控制器数据拷贝。然而,在文件传输过程中,我们实际上并没有对文件进行任何操作,只是将磁盘文件传输给网卡。CPU数据拷贝的次数是由于上下文切换导致CPU在用户态和内核态之间来回复制数据,这是没有必要的。此外,用户缓冲区在整个传输过程中也是没有必要存在的。

如何实现零拷贝

零拷贝技术实现的方式通常有 2 种:

  1. mmap + write
  2. sendfile

让我们来探讨一下如何通过两种方式实现零拷贝技术,从而减少上下文切换和数据拷贝的次数。

mmap(共享缓冲区) + write

首先是使用 mmap + write 的方式。在之前的讨论中,我们了解到在使用 read() 系统调用时,会发生将内核缓冲区的数据拷贝到用户缓冲区的过程。为了减少这一步的开销,可以使用 mmap() 替换 read() 系统调用函数。

我们之前在讨论进程间如何通信时,我们有提到过共享缓冲区,即将内核态的一部分内存空间映射到应用程序所使用的虚拟空间上。如图所示:

image

而我们此时并不需要多个进程通信,如果只需要将物理内存映射给需要文件传输的进程,情况就会变得稍有不同。那么就可以演化成下面的这种方式,如图所示:

image

具体过程如下:

  1. 应用程序调用 mmap() 函数后,DMA会将磁盘数据拷贝到内核态的缓存区上,然后应用程序与操作系统共享这个缓冲区。
  2. 应用程序调用 write(),操作系统直接将内核态中的缓冲区数据拷贝到 socket 缓冲区,此时只在内核态进行操作,不会产生用户态和内核态切换,数据搬运过程由CPU完成。
  3. 最后,将内核的 socket 缓冲区数据拷贝到网卡中的数据缓冲区,这一步由DMA控制器操作。

我们可以得知,通过使用 mmap() 替代 read(),可以减少一次数据拷贝的过程。然而,这仍然不是最理想的零拷贝方式,因为仍然需要通过 CPU 将内核缓冲区的数据拷贝到 socket 缓冲区,且仍然需要进行 4 次上下文切换,因为系统调用仍然发生了两次。

接下来,我们来看第二种实现零拷贝的方式 - sendfile。

sendfile

在 Linux 内核版本 2.1 中,引入了一个名为sendfile()的系统调用函数,它提供了一种更高效的文件发送方法。sendfile()函数的使用方式如下:

#include <sys/socket.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

该函数的前两个参数是目标端和源端的文件描述符,后面两个参数分别表示源端的偏移量和要复制的数据长度。函数的返回值是实际复制数据的长度。

sendfile()函数具有以下优点:

首先,它可以代替之前需要使用read()和write()两个系统调用的操作,从而减少了一次系统调用的开销。尽管sendfile()函数本身仍然需要进行系统调用,但仍然能够减少了2次上下文切换的开销。

其次,该系统调用可以直接将内核缓冲区中的数据复制到套接字缓冲区中,而无需再复制到用户态。这样一来,只需要进行2次上下文切换和3次数据拷贝。下图展示了这一过程的流程:

image

然而,这个过程仍然不能被称为真正的零拷贝技术。如果我们的网卡支持SG-DMA(散射-聚集直接内存访问)技术,与普通的DMA有所不同,那么我们可以进一步减少通过CPU将内核缓冲区中的数据拷贝到套接字缓冲区的过程。

你可以在你的Linux系统上使用以下命令来查看网卡是否支持散射-聚集特性::

$ ethtool -k eth0 | grep scatter-gather
scatter-gather: on

因此,从Linux内核2.4版本开始,在网卡支持SG-DMA技术的情况下,sendfile()系统调用的过程发生了一些变化,具体过程如下:

第一步,通过DMA将磁盘上的数据拷贝到内核缓冲区中;

第二步:内核缓冲区只需要将描述符和数据长度发送给套接字缓冲区,然后将直接通过SG-DMA将内核缓冲区中的数据拷贝到网卡的缓冲区中,这个过程不再需要从操作系统的内核缓冲区中拷贝到套接字缓冲区,从而减少了一次数据拷贝的过程。

因此,在这个过程中,只进行了两次数据拷贝,如下图所示:

image

这就是所谓的零拷贝(Zero-copy)技术,因为我们没有在内存层面进行数据拷贝,也就是说在整个过程中没有使用CPU来传输数据,而是完全依靠DMA来进行数据传输。

相比传统的文件传输方式,零拷贝技术可以减少2次上下文切换和数据拷贝的次数,只需要进行2次上下文切换和数据拷贝,就能完成文件的传输。而且这2次数据拷贝过程都不需要通过CPU,而是由DMA来进行数据传输。

因此,总体来看,零拷贝技术可以将文件传输的性能提升至少一倍以上。值得一提的是,在讲解零拷贝技术时,并没有提到网络协议是在哪个步骤中封装的。大家也应该知道,在内核中完成了网络协议的封装,而不是直接从缓冲区中取出数据并发送给网卡就结束了。

总结

本章主要介绍了零拷贝技术在文件传输中的优化方法。首先,通过减少用户态和内核态之间的上下文切换次数和数据拷贝次数来优化文件传输的性能。其次,介绍了两种实现零拷贝的方式:mmap + write和sendfile。通过使用mmap + write,可以将内核缓冲区的数据直接拷贝到socket缓冲区,减少一次数据拷贝过程。而使用sendfile系统调用,则可以进一步减少系统调用和数据拷贝次数。若网卡支持SG-DMA技术,还可以通过DMA将内核缓冲区的数据直接拷贝到网卡缓冲区,实现真正的零拷贝。

相关文章
|
25天前
|
监控 Linux 测试技术
C++零拷贝网络编程实战:从理论到生产环境的性能优化之路
🌟 蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕C++与零拷贝网络编程,从sendfile到DPDK,实战优化服务器性能,毫秒级响应、CPU降60%。分享架构思维,共探代码星辰大海!
|
10天前
|
机器学习/深度学习 人工智能 监控
上海拔俗AI软件定制:让技术真正为你所用,拔俗网络这样做
在上海,企业正通过AI软件定制破解通用化难题。该模式以业务场景为核心,量身打造智能解决方案,涵盖场景化模型开发、模块化架构设计与数据闭环优化三大技术维度,推动技术与业务深度融合,助力企业实现高效、可持续的数字化转型。
|
1月前
|
监控 前端开发 安全
Netty 高性能网络编程框架技术详解与实践指南
本文档全面介绍 Netty 高性能网络编程框架的核心概念、架构设计和实践应用。作为 Java 领域最优秀的 NIO 框架之一,Netty 提供了异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。本文将深入探讨其 Reactor 模型、ChannelPipeline、编解码器、内存管理等核心机制,帮助开发者构建高性能的网络应用系统。
185 0
|
3月前
|
监控 算法 安全
基于 C# 基数树算法的网络屏幕监控敏感词检测技术研究
随着数字化办公和网络交互迅猛发展,网络屏幕监控成为信息安全的关键。基数树(Trie Tree)凭借高效的字符串处理能力,在敏感词检测中表现出色。结合C#语言,可构建高时效、高准确率的敏感词识别模块,提升网络安全防护能力。
98 2
|
9月前
|
边缘计算 容灾 网络性能优化
算力流动的基石:边缘网络产品技术升级与实践探索
本文介绍了边缘网络产品技术的升级与实践探索,由阿里云专家分享。内容涵盖三大方面:1) 云编一体的混合组网方案,通过边缘节点实现广泛覆盖和高效连接;2) 基于边缘基础设施特点构建一网多态的边缘网络平台,提供多种业务形态的统一技术支持;3) 以软硬一体的边缘网关技术实现多类型业务网络平面统一,确保不同网络间的互联互通。边缘网络已实现全球覆盖、差异化连接及云边互联,支持即开即用和云网一体,满足各行业需求。
263 4
|
10月前
|
负载均衡 网络协议 网络性能优化
动态IP代理技术详解及网络性能优化
动态IP代理技术通过灵活更换IP地址,广泛应用于数据采集、网络安全测试等领域。本文详细解析其工作原理,涵盖HTTP、SOCKS代理及代理池的实现方法,并提供代码示例。同时探讨配置动态代理IP后如何通过智能调度、负载均衡、优化协议选择等方式提升网络性能,确保高效稳定的网络访问。
1034 2
|
5月前
|
调度 Python
探索Python高级并发与网络编程技术。
可以看出,Python的高级并发和网络编程极具挑战,却也饱含乐趣。探索这些技术,你将会发现:它们好比是Python世界的海洋,有穿越风暴的波涛,也有寂静深海的奇妙。开始旅途,探索无尽可能吧!
136 15
|
5月前
|
机器学习/深度学习 算法 PyTorch
Perforated Backpropagation:神经网络优化的创新技术及PyTorch使用指南
深度学习近年来在多个领域取得了显著进展,但其核心组件——人工神经元和反向传播算法自提出以来鲜有根本性突破。穿孔反向传播(Perforated Backpropagation)技术通过引入“树突”机制,模仿生物神经元的计算能力,实现了对传统神经元的增强。该技术利用基于协方差的损失函数训练树突节点,使其能够识别神经元分类中的异常模式,从而提升整体网络性能。实验表明,该方法不仅可提高模型精度(如BERT模型准确率提升3%-17%),还能实现高效模型压缩(参数减少44%而无性能损失)。这一革新为深度学习的基础构建模块带来了新的可能性,尤其适用于边缘设备和大规模模型优化场景。
262 16
Perforated Backpropagation:神经网络优化的创新技术及PyTorch使用指南
|
5月前
|
监控 算法 JavaScript
基于 JavaScript 图算法的局域网网络访问控制模型构建及局域网禁止上网软件的技术实现路径研究
本文探讨局域网网络访问控制软件的技术框架,将其核心功能映射为图论模型,通过节点与边表示终端设备及访问关系。以JavaScript实现DFS算法,模拟访问权限判断,优化动态策略更新与多层级访问控制。结合流量监控数据,提升网络安全响应能力,为企业自主研发提供理论支持,推动智能化演进,助力数字化管理。
140 4