Linux 中的零拷贝技术
一文彻底弄懂零拷贝原理以及java实现

⼀⽂彻底弄懂零拷贝原理以及java实现⽬录零拷贝传统I/O操作存在的性能问题零拷贝技术原理虚拟内存mmap/write ⽅式sendfile ⽅式带有 scatter/gather 的 sendfile⽅式splice ⽅式总结零拷贝零拷贝(Zero-Copy)是⼀种 I/O 操作优化技术,可以快速⾼效地将数据从⽂件系统移动到⽹络接⼝,⽽不需要将其从内核空间复制到⽤户空间。
其在 FTP 或者 HTTP 等协议中可以显著地提升性能。
但是需要注意的是,并不是所有的操作系统都⽀持这⼀特性,⽬前只有在使⽤ NIO 和 Epoll 传输时才可使⽤该特性。
需要注意,它不能⽤于实现了数据加密或者压缩的⽂件系统上,只有传输⽂件的原始内容。
这类原始内容也包括加密了的⽂件内容。
传统I/O操作存在的性能问题如果服务端要提供⽂件传输的功能,我们能想到的最简单的⽅式是:将磁盘上的⽂件读取出来,然后通过⽹络协议发送给客户端。
传统 I/O 的⼯作⽅式是,数据读取和写⼊是从⽤户空间到内核空间来回复制,⽽内核空间的数据是通过操作系统层⾯的 I/O 接⼝从磁盘读取或写⼊。
代码通常如下,⼀般会需要两个系统调⽤:read(file, tmp_buf, len);write(socket, tmp_buf, len);代码很简单,虽然就两⾏代码,但是这⾥⾯发⽣了不少的事情。
⾸先,期间共发⽣了 4 次⽤户态与内核态的上下⽂切换,因为发⽣了两次系统调⽤,⼀次是 read() ,⼀次是 write(),每次系统调⽤都得先从⽤户态切换到内核态,等内核完成任务后,再从内核态切换回⽤户态。
上下⽂切换到成本并不⼩,⼀次切换需要耗时⼏⼗纳秒到⼏微秒,虽然时间看上去很短,但是在⾼并发的场景下,这类时间容易被累积和放⼤,从⽽影响系统的性能。
其次,还发⽣了 4 次数据拷贝,其中两次是 DMA 的拷贝,另外两次则是通过 CPU 拷贝的,下⾯说⼀下这个过程:第⼀次拷贝,把磁盘上的数据拷贝到操作系统内核的缓冲区⾥,这个拷贝的过程是通过 DMA 搬运的。
Linux 中的零拷贝技术,第 2 部分

Linux 中的直接I/O如果应用程序可以直接访问网络接口存储,那么在应用程序访问数据之前存储总线就不需要被遍历,数据传输所引起的开销将会是最小的。
应用程序或者运行在用户模式下的库函数可以直接访问硬件设备的存储,操作系统内核除了进行必要的虚拟存储配置工作之外,不参与数据传输过程中的其它任何事情。
直接I/O 使得数据可以直接在应用程序和外围设备之间进行传输,完全不需要操作系统内核页缓存的支持。
关于直接I/O 技术的具体实现细节可以参看developerWorks 上的另一篇文章”Linux 中直接I/O 机制的介绍” ,本文不做过多描述。
图 1. 使用直接I/O 的数据传输针对数据传输不需要经过应用程序地址空间的零拷贝技术利用mmap()在Linux 中,减少拷贝次数的一种方法是调用mmap() 来代替调用read,比如:首先,应用程序调用了mmap() 之后,数据会先通过DMA 拷贝到操作系统内核的缓冲区中去。
接着,应用程序跟操作系统共享这个缓冲区,这样,操作系统内核和应用程序存储空间就不需要再进行任何的数据拷贝操作。
应用程序调用了write() 之后,操作系统内核将数据从原来的内核缓冲区中拷贝到与socket 相关的内核缓冲区中。
接下来,数据从内核socket 缓冲区拷贝到协议引擎中去,这是第三次数据拷贝操作。
图 2. 利用mmap() 代替read()通过使用mmap() 来代替read(), 已经可以减半操作系统需要进行数据拷贝的次数。
当大量数据需要传输的时候,这样做就会有一个比较好的效率。
但是,这种改进也是需要代价的,使用mma()p 其实是存在潜在的问题的。
当对文件进行了内存映射,然后调用write() 系统调用,如果此时其他的进程截断了这个文件,那么write() 系统调用将会被总线错误信号SIGBUS 中断,因为此时正在执行的是一个错误的存储访问。
这个信号将会导致进程被杀死,解决这个问题可以通过以下这两种方法:1.为SIGBUS 安装一个新的信号处理器,这样,write() 系统调用在它被中断之前就返回已经写入的字节数目,errno 会被设置成success。
linux copy命令的用法

linux copy命令的用法Linux Copy命令的用法Linux Copy命令是Linux系统中最常用的命令之一,它的作用是将一个文件或者目录复制到另一个位置。
Copy命令的语法如下:cp [选项] 源文件目标文件其中,选项是可选的,源文件是要复制的文件或目录,目标文件是复制后的文件或目录。
Copy命令的常用选项Copy命令有很多选项,下面介绍几个常用的选项:-r:复制目录及其子目录和文件。
-f:强制复制,即覆盖目标文件。
-i:交互式复制,即在复制前询问是否覆盖目标文件。
-v:显示复制的详细信息。
-p:保留源文件的权限、所有者和时间戳等属性。
Copy命令的使用示例1. 复制文件要将一个文件复制到另一个位置,可以使用以下命令:cp file1.txt /home/user1/这个命令将file1.txt文件复制到/home/user1/目录下。
2. 复制目录要将一个目录及其子目录和文件复制到另一个位置,可以使用以下命令:cp -r dir1 /home/user1/这个命令将dir1目录及其子目录和文件复制到/home/user1/目录下。
3. 强制复制如果目标文件已经存在,可以使用-f选项强制复制,覆盖目标文件。
例如:cp -f file1.txt /home/user1/这个命令将file1.txt文件强制复制到/home/user1/目录下,如果目标文件已经存在,则会被覆盖。
4. 交互式复制如果不确定是否要覆盖目标文件,可以使用-i选项交互式复制。
例如:cp -i file1.txt /home/user1/这个命令将file1.txt文件复制到/home/user1/目录下,如果目标文件已经存在,则会询问是否覆盖。
5. 显示详细信息如果想要显示复制的详细信息,可以使用-v选项。
例如:cp -v file1.txt /home/user1/这个命令将file1.txt文件复制到/home/user1/目录下,并显示复制的详细信息。
剖析linux下的零拷贝技术

剖析linux下的零拷贝技术背景大多数的网络服务器是基于server-client模式的。
在这当中,下载是一个很常见的功能。
此时服务器端需要将主机磁盘上的文件发送到客户端上去。
传统的Linux操作系统的标准I/O接口是基于数据拷贝操作的,即I/O操作会导致数据在操作系统内核地址空间的缓冲区和应用程序地址空间定义的缓冲区之间进行传输。
那么传统的I/O操作过程是咋样的呢?(下面是具体说明,以read和write为例)在执行read操作时,操作系统首先会检查,文件内容是否缓存在内核缓冲区,如果在内核缓冲区,则不用去磁盘中读取文件,而是直接将内核缓冲区的内容拷贝到用户空间缓冲区中去。
如果不是,操作系统则首先将磁盘上的数据拷贝的内核缓冲区(DMA),然后再把内核缓冲区上的内容拷贝到用户缓冲区中。
接下来,write系统调用再把用户缓冲区的内容拷贝到网络堆栈相关的内核缓冲区中,最后再往对方的sockfd中些数据。
并且在这个过程中还涉及到了四次的上下文切换。
那传统的I/O操作会带来什么问题呢?在高速网络中,大量传统的I/O操作导致的数据拷贝工作会占用CPU 时间片,同时也需要占用额外的内存带宽。
使cpu将大多数的时间用于I/O操作上,从而无法处理其他的任务,很大程度上影响了系统的性能,使服务器成为性能瓶颈。
而本身我们可以看出:很多数据复制操作并不是真正需要的。
所以可以消除一些复制操作以减少开销并提高性能。
这就引出了我们今天要介绍的“零拷贝”技术。
概念零拷贝(Zero-copy)技术是指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域。
这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。
零拷贝技术可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间不必要的中间拷贝次数,从而有效地提高数据传输效率。
而且,零拷贝技术减少了用户进程地址空间和内核地址空间之间因为上下文切换而带来的开销。
零拷贝的概念 -回复

零拷贝的概念-回复什么是零拷贝?在计算机系统中,数据的传输一般需要经过拷贝的过程。
传统的数据传输方式,数据从一个地方拷贝到内核缓冲区,然后再从内核缓冲区拷贝到目标地点。
这种过程涉及到数据的多次拷贝,不仅增加了CPU和内存的负担,还会降低系统的效率。
为了提高数据传输的速度和效率,零拷贝技术被提出。
零拷贝技术是指在数据传输过程中,避免数据的多次复制,尽量减少对CPU和内存资源的使用,以提高数据传输的效率。
零拷贝技术在操作系统、网络通信、文件系统等领域都得到了广泛应用。
零拷贝技术的核心思想是将数据的拷贝操作转移到硬件或操作系统层面上,减少CPU和内存的参与。
具体来说,零拷贝技术主要有以下几个关键技术:1. 零拷贝文件传输:传统的文件传输需要从磁盘读取文件数据到内存缓冲区,然后再将数据从内存缓冲区拷贝到网络缓冲区,最后通过网络发送出去。
而零拷贝技术可以直接从磁盘读取数据到网络缓冲区,避免了中间的内存拷贝。
2. 零拷贝网络传输:在网络传输中,通常需要将数据从一个网络缓冲区拷贝到另一个网络缓冲区。
零拷贝技术可以通过操作系统提供的零拷贝API,直接将数据从一个网络缓冲区传输到另一个网络缓冲区,避免了数据的多次复制。
3. 零拷贝内存管理:传统的内存管理方式中,应用程序需要将数据拷贝到内核缓冲区,然后再由内核缓冲区将数据拷贝到目标内存区域。
零拷贝技术可以通过使用共享内存等方式,将数据直接写入目标内存区域,避免了中间的内存拷贝。
零拷贝技术的应用带来了显著的性能优势。
首先,由于减少了数据的多次拷贝,可以节省CPU的使用,减少了CPU的负担,提高了系统的吞吐量。
其次,由于减少了内存的使用,可以降低内存的消耗,提高了内存的利用率。
此外,零拷贝技术还可以减少数据传输的延迟,提高了系统的响应速度。
然而,零拷贝技术并非适用于所有场景。
由于零拷贝技术需要硬件或操作系统的支持,因此其应用范围受到一定的限制。
此外,由于零拷贝技术涉及到底层的硬件和操作系统细节,开发和调试的复杂性较高,需要具备较强的技术实力。
Linux环境下普适性零拷贝平台的研究与实现

关键词 :零拷 贝; 普适性;内 存映射 ; i x N P Ln ; A I u
中图分 类号 :T 3 3 P9 文 献标 志码 :A 文章编 号 :10 —65 2 1 )7 22 —4 0 139 (0 10 .6 10
d i1 . 9 9 ji n 10 -6 5 2 1 . 7 0 2 o :0 3 6 / .s .0 13 9 .0 10 .6 s
Co p e t he c mmo r prea y p afr s f z r —op m  ̄ d wi t o h n p o i tr l t m o e o c y, is p ro ma c s g t a c ran i p o e n , t plto m o t e fr n e ha o e i m r v me t he af r t
为休眠的零拷贝程序构建 了红黑树 队列 , 通过设置较 大的睡眠
时间来 唤醒零拷 贝程 序 , 以达到 避免 中 断湮 没 的 目的 。其 次 Z rP通过 函数 e00 c a—x i eo l0 一 l n r—r 网卡 的接 收 队列 进行 e q对
限等 问题 , 不能够得到普遍应用 。
பைடு நூலகம்
0 引言
作为报文捕获前端 , 数据包捕获技术普遍应 用于高性能路 由器 、 硬件防火墙 、 侵检测 系统等 领域 中。关 于数 据包捕 获 入
技术的研究 和讨论 已有很 多 , 国外 的 P — IG… 、C p ; 如 F RN n a 国 内的 U S3、 P C [ R N C 、 eo [ U C 等 。这 MP [ H P P 、 T P 【 Z r 、 P [ ] P
( ai a ii l wt i ytm E gneig& Tcn l i l e ac et , hnzo 50 2, hn ) N t n l gt ihn Ss n i r o D aS c g e e n eh oo c s r Cne Z egh u40 0 C ia gaR e h r
Linux零拷贝原理

Linux零拷贝原理到目前为止,几乎所有人都听说过Linux下所谓的零拷贝功能,但我经常遇到对这个主题没有完全了解的人。
正因为如此,我决定写几篇文章,深入探讨这个问题,希望能解开这个有用的特性。
在这篇文章中,我们从一个用户的角度看零拷贝,血淋淋的内核级细节被有意省略。
什么是零拷贝?为了更好地理解问题的解决方案,我们首先需要了解问题本身。
让我们来看看网络服务器处理的简单过程中所涉及到的内容,它将存储在文件中的数据存储到网络上的客户端中。
这里有一些示例代码:看起来很简单;你会认为只有这两个系统调用不会有太多的开销. 事实上,这与事实并无太大的距离。
在这两个调用的后面,数据至少被复制了4次,并且几乎已经执行了许多用户/内核上下文切换(实际上这个过程要复杂得多,但我想让它保持简单)。
为了更好地了解所涉及的过程,请看图1。
顶部显示了上下文切换,而底部显示了复制操作。
图1。
在两个示例系统调用中复制第一步:读系统调用会导致从用户模式到内核模式的上下文切换。
第一个复制由DMA引擎执行,它读取磁盘中的文件内容并将其存储到内核地址空间缓冲区中。
第二步:将数据从内核缓冲区复制到用户缓冲区,read系统调用返回。
调用的返回导致了从内核返回到用户模式的上下文切换,现在,数据存储在用户地址空间缓冲区中,它可以再次开始向下移动。
第三步:write系统调用导致从用户模式到内核模式的上下文切换,执行第三个复制,将数据再次放入内核地址空间缓冲区中。
但是这一次,数据被放入一个不同的缓冲区,这个缓冲区是与套接字相关联的。
第四步:写系统调用返回,创建第四个上下文切换。
DMA引擎将数据从内核缓冲区传递到协议engin时,第四个复制发生了独立和异步的情况。
你可能会问自己,“你说的独立和异步是什么意思?”在调用返回之前,数据不是传输的吗?”实际上,调用返回并不能保证传输;它甚至不能保证传输的开始。
它只是意味着以太网驱动程序在其队列中有空闲的描述符并接受了我们的传输数据,在我们的之前可能会有很多的数据包在排队。
mmap和sendfile使用方法

文章标题:深度探析mmap和sendfile的使用方法一、引言在计算机领域,mmap和sendfile是两种常见的IO操作方式,它们可以有效提高文件的读写效率,降低系统开销。
本文将从浅入深地探讨mmap和sendfile的使用方法,帮助读者更深入地理解这两种技术。
二、mmap的使用方法1. 什么是mmapmmap是一种内存映射文件的技术,它将文件映射到进程的位置区域空间,使得文件可以直接在内存中进行读写操作,而不需要通过系统调用。
2. 使用方法在Linux系统中,使用mmap可以通过以下步骤进行:(1)打开文件:使用open系统调用打开需要映射的文件。
(2)映射文件到内存:使用mmap系统调用将文件映射到进程的位置区域空间。
(3)读写文件:通过访问内存的方式进行文件的读写操作。
(4)解除映射:完成文件读写操作后,使用munmap系统调用将文件从进程的位置区域空间解除映射。
3. 优缺点优点:mmap能够减少系统调用次数,提高文件读写效率,适用于大文件的读写操作。
缺点:当文件较小或需要频繁读写时,mmap的性能可能比较低,且对内存消耗较大。
三、sendfile的使用方法1. 什么是sendfilesendfile是一种零拷贝技术,它可以在内核和用户空间直接进行文件的传输,提高网络IO的效率。
2. 使用方法在Linux系统中,使用sendfile可以通过以下步骤进行:(1)打开文件:使用open系统调用打开需要传输的文件。
(2)传输文件:使用sendfile系统调用将文件内容传输至套接字。
(3)关闭文件:完成文件传输后,使用close系统调用关闭文件描述符。
3. 优缺点优点:sendfile通过内核和用户空间的直接传输,避免了数据在内核空间和用户空间的多次复制,提高了文件传输效率。
缺点:sendfile只能用于文件到套接字的传输,不适用于文件的读写操作,且需要特定的系统支持。
四、个人观点和理解mmap和sendfile是两种不同的IO操作方式,各自适用于不同的场景。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Linux 中的零拷贝技术概述黄晓晨, 软件工程师, IBM黄晓晨,IBM system Z 自动化技术支持软件工程师。
冯瑞, 软件工程师, IBM简介:本系列由两篇文章组成,介绍了当前用于Linux 操作系统上的几种零拷贝技术,简单描述了各种零拷贝技术的实现,以及它们的特点和适用场景。
本文是本系列文章的第一部分,主要是介绍一些零拷贝技术的相关背景知识,简要概述了Linux 为什么需要零拷贝技术以及Linux 中都有哪几种零拷贝技术。
引言传统的Linux 操作系统的标准I/O 接口是基于数据拷贝操作的,即I/O 操作会导致数据在操作系统内核地址空间的缓冲区和应用程序地址空间定义的缓冲区之间进行传输。
这样做最大的好处是可以减少磁盘I/O 的操作,因为如果所请求的数据已经存放在操作系统的高速缓冲存储器中,那么就不需要再进行实际的物理磁盘I/O 操作。
但是数据传输过程中的数据拷贝操作却导致了极大的CPU 开销,限制了操作系统有效进行数据传输操作的能力。
零拷贝(zero-copy )这种技术可以有效地改善数据传输的性能,在内核驱动程序(比如网络堆栈或者磁盘存储驱动程序)处理I/O 数据的时候,零拷贝技术可以在某种程度上减少甚至完全避免不必要CPU 数据拷贝操作。
现代的CPU 和存储体系结构提供了很多特征可以有效地实现零拷贝技术,但是因为存储体系结构非常复杂,而且网络协议栈有时需要对数据进行必要的处理,所以零拷贝技术有可能会产生很多负面的影响,甚至会导致零拷贝技术自身的优点完全丧失。
为什么需要零拷贝技术如今,很多网络服务器都是基于客户端- 服务器这一模型的。
在这种模型中,客户端向服务器端请求数据或者服务;服务器端则需要响应客户端发出的请求,并为客户端提供它所需要的数据。
随着网络服务的逐渐普及,video 这类应用程序发展迅速。
当今的计算机系统已经具备足够的能力去处理video 这类应用程序对客户端所造成的重负荷,但是对于服务器端来说,它应付由video 这类应用程序引起的网络通信量就显得捉襟见肘了。
而且,客户端的数量增长迅速,那么服务器端就更容易成为性能瓶颈。
而对于负荷很重的服务器来说,操作系统通常都是引起性能瓶颈的罪魁祸首。
举个例子来说,当数据“写”操作或者数据“发送”操作的系统调用发出时,操作系统通常都会将数据从应用程序地址空间的缓冲区拷贝到操作系统内核的缓冲区中去。
操作系统这样做的好处是接口简单,但是却在很大程度上损失了系统性能,因为这种数据拷贝操作不单需要占用CPU 时间片,同时也需要占用额外的内存带宽。
一般来说,客户端通过网络接口卡向服务器端发送请求,操作系统将这些客户端的请求传递给服务器端应用程序,服务器端应用程序会处理这些请求,请求处理完成以后,操作系统还需要将处理得到的结果通过网络适配器传递回去。
下边这一小节会跟读者简单介绍一下传统的服务器是如何进行数据传输的,以及这种数据传输的处理过程存在哪些问题有可能会造成服务器的性能损失。
Linux 中传统服务器进行数据传输的流程Linux 中传统的I/O 操作是一种缓冲I/O,I/O 过程中产生的数据传输通常需要在缓冲区中进行多次的拷贝操作。
一般来说,在传输数据的时候,用户应用程序需要分配一块大小合适的缓冲区用来存放需要传输的数据。
应用程序从文件中读取一块数据,然后把这块数据通过网络发送到接收端去。
用户应用程序只是需要调用两个系统调用read() 和write() 就可以完成这个数据传输操作,应用程序并不知晓在这个数据传输的过程中操作系统所做的数据拷贝操作。
对于Linux 操作系统来说,基于数据排序或者校验等各方面因素的考虑,操作系统内核会在处理数据传输的过程中进行多次拷贝操作。
在某些情况下,这些数据拷贝操作会极大地降低数据传输的性能。
当应用程序需要访问某块数据的时候,操作系统内核会先检查这块数据是不是因为前一次对相同文件的访问而已经被存放在操作系统内核地址空间的缓冲区内,如果在内核缓冲区中找不到这块数据,Linux 操作系统内核会先将这块数据从磁盘读出来放到操作系统内核的缓冲区里去。
如果这个数据读取操作是由DMA 完成的,那么在DMA 进行数据读取的这一过程中,CPU 只是需要进行缓冲区管理,以及创建和处理DMA ,除此之外,CPU 不需要再做更多的事情,DMA 执行完数据读取操作之后,会通知操作系统做进一步的处理。
Linux 操作系统会根据read() 系统调用指定的应用程序地址空间的地址,把这块数据存放到请求这块数据的应用程序的地址空间中去,在接下来的处理过程中,操作系统需要将数据再一次从用户应用程序地址空间的缓冲区拷贝到与网络堆栈相关的内核缓冲区中去,这个过程也是需要占用CPU 的。
数据拷贝操作结束以后,数据会被打包,然后发送到网络接口卡上去。
在数据传输的过程中,应用程序可以先返回进而执行其他的操作。
之后,在调用write() 系统调用的时候,用户应用程序缓冲区中的数据内容可以被安全的丢弃或者更改,因为操作系统已经在内核缓冲区中保留了一份数据拷贝,当数据被成功传送到硬件上之后,这份数据拷贝就可以被丢弃。
从上面的描述可以看出,在这种传统的数据传输过程中,数据至少发生了四次拷贝操作,即便是使用了DMA 来进行与硬件的通讯,CPU 仍然需要访问数据两次。
在read() 读数据的过程中,数据并不是直接来自于硬盘,而是必须先经过操作系统的文件系统层。
在write() 写数据的过程中,为了和要传输的数据包的大小相吻合,数据必须要先被分割成块,而且还要预先考虑包头,并且要进行数据校验和操作。
图 1. 传统使用read 和write 系统调用的数据传输零拷贝(zero copy)技术概述什么是零拷贝?简单一点来说,零拷贝就是一种避免CPU 将数据从一块存储拷贝到另外一块存储的技术。
针对操作系统中的设备驱动程序、文件系统以及网络协议堆栈而出现的各种零拷贝技术极大地提升了特定应用程序的性能,并且使得这些应用程序可以更加有效地利用系统资源。
这种性能的提升就是通过在数据拷贝进行的同时,允许CPU 执行其他的任务来实现的。
零拷贝技术可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间不必要的中间拷贝次数,从而有效地提高数据传输效率。
而且,零拷贝技术减少了用户应用程序地址空间和操作系统内核地址空间之间因为上下文切换而带来的开销。
进行大量的数据拷贝操作其实是一件简单的任务,从操作系统的角度来说,如果CPU 一直被占用着去执行这项简单的任务,那么这将会是很浪费资源的;如果有其他比较简单的系统部件可以代劳这件事情,从而使得CPU 解脱出来可以做别的事情,那么系统资源的利用则会更加有效。
综上所述,零拷贝技术的目标可以概括如下:避免数据拷贝o避免操作系统内核缓冲区之间进行数据拷贝操作。
o避免操作系统内核和用户应用程序地址空间这两者之间进行数据拷贝操作。
o用户应用程序可以避开操作系统直接访问硬件存储。
o数据传输尽量让DMA 来做。
将多种操作结合在一起o避免不必要的系统调用和上下文切换。
o需要拷贝的数据可以先被缓存起来。
o对数据进行处理尽量让硬件来做。
前文提到过,对于高速网络来说,零拷贝技术是非常重要的。
这是因为高速网络的网络链接能力与CPU 的处理能力接近,甚至会超过CPU 的处理能力。
如果是这样的话,那么CPU 就有可能需要花费几乎所有的时间去拷贝要传输的数据,而没有能力再去做别的事情,这就产生了性能瓶颈,限制了通讯速率,从而降低了网络链接的能力。
一般来说,一个CPU 时钟周期可以处理一位的数据。
举例来说,一个1 GHz 的处理器可以对1Gbit/s 的网络链接进行传统的数据拷贝操作,但是如果是10 Gbit/s 的网络,那么对于相同的处理器来说,零拷贝技术就变得非常重要了。
对于超过1 Gbit/s 的网络链接来说,零拷贝技术在超级计算机集群以及大型的商业数据中心中都有所应用。
然而,随着信息技术的发展,1 Gbit/s,10 Gbit/s 以及100 Gbit/s 的网络会越来越普及,那么零拷贝技术也会变得越来越普及,这是因为网络链接的处理能力比CPU 的处理能力的增长要快得多。
传统的数据拷贝受限于传统的操作系统或者通信协议,这就限制了数据传输性能。
零拷贝技术通过减少数据拷贝次数,简化协议处理的层次,在应用程序和网络之间提供更快的数据传输方法,从而可以有效地降低通信延迟,提高网络吞吐率。
零拷贝技术是实现主机或者路由器等设备高速网络接口的主要技术之一。
现代的CPU 和存储体系结构提供了很多相关的功能来减少或避免I/O 操作过程中产生的不必要的CPU 数据拷贝操作,但是,CPU 和存储体系结构的这种优势经常被过高估计。
存储体系结构的复杂性以及网络协议中必需的数据传输可能会产生问题,有时甚至会导致零拷贝这种技术的优点完全丧失。
在下一章中,我们会介绍几种Linux 操作系统中出现的零拷贝技术,简单描述一下它们的实现方法,并对它们的弱点进行分析。
零拷贝技术分类零拷贝技术的发展很多样化,现有的零拷贝技术种类也非常多,而当前并没有一个适合于所有场景的零拷贝技术的出现。
对于Linux 来说,现存的零拷贝技术也比较多,这些零拷贝技术大部分存在于不同的Linux 内核版本,有些旧的技术在不同的Linux 内核版本间得到了很大的发展或者已经渐渐被新的技术所代替。
本文针对这些零拷贝技术所适用的不同场景对它们进行了划分。
概括起来,Linux 中的零拷贝技术主要有下面这几种:∙直接I/O:对于这种数据传输方式来说,应用程序可以直接访问硬件存储,操作系统内核只是辅助数据传输:这类零拷贝技术针对的是操作系统内核并不需要对数据进行直接处理的情况,数据可以在应用程序地址空间的缓冲区和磁盘之间直接进行传输,完全不需要Linux 操作系统内核提供的页缓存的支持。
∙在数据传输的过程中,避免数据在操作系统内核地址空间的缓冲区和用户应用程序地址空间的缓冲区之间进行拷贝。
有的时候,应用程序在数据进行传输的过程中不需要对数据进行访问,那么,将数据从Linux 的页缓存拷贝到用户进程的缓冲区中就可以完全避免,传输的数据在页缓存中就可以得到处理。
在某些特殊的情况下,这种零拷贝技术可以获得较好的性能。
Linux 中提供类似的系统调用主要有mmap(),sendfile() 以及splice()。
对数据在Linux 的页缓存和用户进程的缓冲区之间的传输过程进行优化。
该零拷贝技术侧重于灵活地处理数据在用户进程的缓冲区和操作系统的页缓存之间的拷贝操作。
这种方法延续了传统的通信方式,但是更加灵活。
在Linux 中,该方法主要利用了写时复制技术。
前两类方法的目的主要是为了避免应用程序地址空间和操作系统内核地址空间这两者之间的缓冲区拷贝操作。