零拷贝(Zerocopy)及其应用详解.docxVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
零拷贝(Zero-copy)及其应用详解 2021-12-31 前言 零拷贝(Zero-copy)是一种高效的数据传输机制,在追求低延迟的传输场景中格外常用。本文先通过传统方案引出零拷贝机制,然后分析其细节,最终引见它的部分应用。 文中涉及到的操作系统理论学问都可以参考英文维基或者相关书籍,如Abraham Silberschatz著《操作系统概念》、Andrew S. Tanenbaum著《现代操作系统》等。 传统的数据传输方法 在互联网时代,从某台机器将一份数据(比如一个文件)通过网络传输到另外一台机器,是再平常不过的事情了。假如依据一般的思路,用Java言语来描述发送端的规律,大致如下。 Socket socket = new Socket(HOST, PORT); InputStream inputStream = new FileInputStream(FILE_PATH); OutputStream outputStream = new DataOutputStream(socket.getOutputStream()); byte[] buffer = new byte[4096]; while (inputStream.read(buffer) = 0) { outputStream.write(buffer); } outputStream.close(); socket.close(); inputStream.close(); 看起来当然是很简约的。但是假如我们深化到操作系统的层面,就会发觉实际的微观操作要更简单,具体来说有以下步骤: JVM向OS发出read()系统调用,触发上下文切换,从用户态切换到内核态。 从外部存储(如硬盘)读取文件内容,通过直接内存访问(DMA)存入内核地址空间的缓冲区。 将数据从内核缓冲区拷贝到用户空间缓冲区,read()系统调用前往,并从内核态切换回用户态。 JVM向OS发出write()系统调用,触发上下文切换,从用户态切换到内核态。 将数据从用户缓冲区拷贝到内核中与目的地Socket关联的缓冲区。 数据最终经由Socket通过DMA传送到硬件(如网卡)缓冲区,write()系统调用前往,并从内核态切换回用户态。 假如言语描述看起来有些乱的话,通过时序图描述会更清楚一些。 传统方法的时序图 到了这一步,你能否觉得简约的代码规律下隐蔽着很累赘的东西了?现实也的确如此,这个过程一共发生了4次上下文切换(严格来讲是模式切换),并且数据也被来回拷贝了4次。假如忽视掉系统调用的细节,整个过程可以用下面的两张简图表示。 传统方法的流程框图 传统方法的上下文切换过程 我们都晓得,上下文切换是CPU密集型的工作,数据拷贝是I/O密集型的工作。假如一次简约的传输就要像上面这样简单的话,效率是相当低下的。零拷贝机制的终极目标,就是衰退冗余的上下文切换和数据拷贝,提高效率。 零拷贝的数据传输方法 “基础的”零拷贝机制 通过上面的分析可以看出,第2、3次拷贝(也就是从内核空间到用户空间的来回复制)是没有意义的,数据应当可以直接从内核缓冲区直接送入Socket缓冲区。零拷贝机制就实现了这一点。不过零拷贝需要由操作系统直接支持,不同OS有不同的实现方法。大多数Unix-like系统都是供应了一个名为sendfile()的系统调用,在其man page中,就有这样的描述: sendfile() copies data between one file descriptor and another. Because this copying is done within the kernel, sendfile() is more efficient than the combination of read(2) and write(2), which would require transferring data to and from user space. 下面是零拷贝机制下,数据传输的时序图。 零拷贝方法的时序图 可见的确是衰退了从内核空间到用户空间的来回复制,因而“zero-copy”这个词实际上是站在内核的角度来说的,并不是完全不会发生任何拷贝。 在Java NIO包中供应了零拷贝机制对应的API,即FileChannel.transferTo()方法。不过FileChannel类是笼统类,transferTo()也是一个笼统方法,因而还要依靠于具体实现。FileChannel的实现类并不在JDK本身,而位于sun.nio.ch.FileChannelImpl类中,零拷贝的具体实现自然也都是native方法,看官如有爱好可以自行查找源码来看,这里不再赘述。 将传统方式的发

文档评论(0)

136****7795 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档