对于所有的io操作,底层一定是调用操作系统的api来进行读写。受限于不同的操作系统,操作方式一定是有差异的。以下read和write操作,可以看做服务器从磁盘硬件上读取文件数据,然后通过socket发送给客户端的流程

传统io服务端对客户端的传输

对于读操作:jvm虚拟机一定会发送一个read()操作系统级别的方法,由此会产生一个上下文的切换,从程序所在的用户空间切换至系统的内核空间,内核空间向磁盘空间请求数据,通过DMA直接内存访问的方式将数据读取到内核空间缓冲区,此时用户空间是无法直接使用的,所以下面会将这份缓冲数据原封不动的拷贝到用户空间,至此read操作就结束。期间有两次上下文的切换,和两次数据的拷贝

对于写操作:将文件读取之后需要发送给远端socket客户端。同样调用系统级别的write方法,需要将上述读到的用户空间的数据原封不动的拷贝到内核上的socket缓冲区,然后DMA 引擎将数据从该缓冲区传到协议引擎,这一次拷贝独立地、异步地发生 。

对于这种io的操作,用户空间只是作为一个中转站,会和内核空间有不必要的上下文切换和数据之间的拷贝

操作系统对于io的一种优化方式

对于优化方式,需要系统直接的支持,jvm是无法提供任何的帮助。对于传统的linux、unix等操作系统是支持的

对于读写操作:用户空间向操作系统发送sendfile()方法,后续的操作只会在内核空间完成。对于所有的读写操作将只会有两次的用户空间和内核空间切换,这种操作称为操作系统意义上的零拷贝。同样的后续会通过DMA的方式向磁盘空间读取数据,读到内核空间的缓冲区,然后将这部分数据写到socket缓冲区,然后通过socket缓冲区向客户端发送数据,完成之后向内核空间然后向用户空间发送数据。相比于第一种方式有了极大的改善。

io的进一步优化方式

相对于上一种方案,内核空间会将数据复制一份到socket缓冲区,因为对于DMA直接内存访问的机制,希望内存地址是连续的,当然buffer的地址是连续的,因此会多一步拷贝到socket缓冲区,如果操作系统支持buffer中的scatter/gather,那么我们就能够有效的避免这种问题。可以通过scatter/gather的方式来读取数据到内核空间然后直接进行后续的写操作,从而减少中间的一步拷贝。

最佳的方式

通过DMA的方式拷贝数据到内核缓冲区,将对应的文件描述符写到socket buffer中,包含了内核的缓冲区的地址和数据长度,并不需要将数据拷贝到socket buffer中,只用存文件描述符。最后协议引擎发送数据的时候,从kernel buffer和socket buffer里面读取数据,对于kernel buffer是真实数据的读取,而对于socket buffer是文件描述符的读取,通过gather操作最终一起发送给客户端

很多的web应用程序都支持零拷贝,比如apache和tomcat,Java中提供的nio的方式是通过transferTo来实现

对于我们上面所述的所有方式,用户是无法对文件进行一定的操作。我们可以通过内存映射在中间过程来对文件进行一定的操作:

参考:

http://xcorpion.tech/2016/09/10/It-s-all-about-buffers-zero-copy-mmap-and-Java-NIO/ 
https://www.ibm.com/developerworks/library/j-zerocopy/

http://www.linuxjournal.com/article/6345?page=0,0

java-nio之zero copy深入分析的更多相关文章

  1. Java NIO使用及原理分析(1-4)(转)

    转载的原文章也找不到!从以下博客中找到http://blog.csdn.net/wuxianglong/article/details/6604817 转载自:李会军•宁静致远 最近由于工作关系要做一 ...

  2. 攻破JAVA NIO技术壁垒

    转载自攻破JAVA NIO技术壁垒 概述 NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector.传统IO基于字节流和字符流进行操作,而NIO基于Channel和 ...

  3. Java Se : Java NIO(服务端)与BIO(客户端)通信

    Java目前有三种IO相关的API了,下面简单的说一下: BIO,阻塞IO,最常用的Java IO API,提供一般的流的读写功能.相信学习Java的人,都用过. NIO,非阻塞IO,在JDK1.4中 ...

  4. Java NIO 基础

    Java在JDK1.4中引入了 java.nio 类库,为Java进军后端Server和中间件开发打开了方便之门. 一般而言,这里的 nio 代表的是 New I/O,但是从实质上来说,我们可以将其理 ...

  5. Java NIO教程 文件系统

    在NIO.2的文件系统中,Path是一切操作的基础.Path准确来说,代表着文件系统中的位置.可以代表一个目录(也就是通常所说的文件夹),也可以代表一个文件. 在新文件系统中,还有一个不得不说的就是F ...

  6. Java NIO教程 MappedByteBuffer

    之前跟大家说过,要讲MappedByteBuffer,现在我来履行承诺了. 首先从大体上讲一下MappedByteBuffer究竟是什么.从继承结构上来讲,MappedByteBuffer继承自Byt ...

  7. JAVA NIO是什么(zz)

    JAVA NIO是什么? 1.   基本 概念 IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. 所有语言运行时系 ...

  8. Java NIO、NIO.2学习笔记

    相关学习资料 http://www.molotang.com/articles/903.html http://www.ibm.com/developerworks/cn/education/java ...

  9. 【转载】高性能IO设计 & Java NIO & 同步/异步 阻塞/非阻塞 Reactor/Proactor

    开始准备看Java NIO的,这篇文章:http://xly1981.iteye.com/blog/1735862 里面提到了这篇文章 http://xmuzyq.iteye.com/blog/783 ...

  10. Java Nio 多线程网络下载

    --> 默认最多50个线程 同一文件下载失败延迟超过30秒就结束下载 --> 下载5分钟超时时间,假设5分钟内未下载完就结束下载 --> 依赖 commons-httpclient ...

随机推荐

  1. P3512 [POI2010]PIL-Pilots

    P3512 [POI2010]PIL-Pilots我一开始打的O(n^2)(最坏情况)的算法.枚举区间长度.60分 #include<iostream> #include<cstdi ...

  2. mysql varchar 转 decimal

    在我们写代码的实际业务中,有时候实体类用的是String,数据库中自然是VARCHAR类型,但是如果这个实体的属性值放的是数字类型,你查询的时候又需要对它进行排序.sql怎么写呢. 别担心MySQL提 ...

  3. CSS3选择器01—CSS2.1部分选择器

    这篇文章主要用于存储CSS以及CSS3的选择器部分知识,以便日后查阅及记忆. 该内容分为两部分,第一部分为css选择器的一些基本知识.第二部分为CSS3新增加的选择器. 在开始之前,先简单介绍一下选择 ...

  4. [代码审计]云优cms V 1.1.2前台多处sql注入,任意文件删除修复绕过至getshell

    0X00 总体简介 云优CMS于2017年9月上线全新版本,二级域名分站,内容分站独立,七牛云存储,自定义字段,自定义表单,自定义栏目权限,自定义管理权限等众多功能深受用户青睐,上线短短3个月,下载次 ...

  5. 洛谷 P1135 奇怪的电梯

    题目描述 呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯.大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N).电梯只有四个按钮:开 ...

  6. BZOJ.1926.[SDOI2010]粟粟的书架(前缀和 主席树 二分)

    题目链接 题意: 在给定矩形区域内找出最少的数,满足和>=k.输出数的个数.两种数据范围. 0~50 注意到(真没注意到...)P[i,j]<=1000,我们可以利用前缀和预处理. num ...

  7. 解决 PermGen space Tomcat内存设置(转)

    在使用Java程序从数据库中查询大量的数据或是应用服务器(如tomcat.jboss,weblogic)加载jar包时会出现java.lang.OutOfMemoryError异常.这主要是由于应用服 ...

  8. 设计模式之七:模板方法模式(Template Method)

    模板方法模式: 定义了一个算法的基本操作骨架,并将算法的一些步骤延迟到子类中来实现. 模板方法模式让子类在不更改算法结构的前提下能够又一次定义算法的一些步骤. Define the skeleton ...

  9. SQL Server、Oracle和MySQL中查出值为NULL的替换

    参考文献: http://database.51cto.com/art/200803/67397.htm 正文 在SQL Server Oracle MySQL当数据库中查出某值为NULL怎么办? 1 ...

  10. Go - 反射中 函数 和 方法 的调用 - v.Call()

    上一篇文章 说到了 Golang 中的反射的一些基本规则,重点就是文章中最后的三点,但是这篇文章并没有说如何在反射中调用函数和方法,这就是接下来要说的. 反射中调用 函数 众所周知,Golang 中的 ...