对于所有的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. 20172301 《Java软件结构与数据结构》实验三报告

    20172301 <Java软件结构与数据结构>实验三报告 课程:<Java软件结构与数据结构> 班级: 1723 姓名: 郭恺 学号:20172301 实验教师:王志强老师 ...

  2. 002.SSH日常命令

    一 远程登陆 ssh 用户名@远程主机ip:首次登陆需要下载对方公钥. 实例:ssh 192.168.10.129 二 远程复制 scp root@远程主机ip:[远程主机文件绝对路径] [需要保存的 ...

  3. 数据包编辑工具bittwiste

    数据包编辑工具bittwiste   bittwiste是数据包重放工具bittwist的一个工具.该工具可以编辑修改PCAP抓包文件.该工具提供数据包过滤功能,如根据范围和时间过滤.同时,该工具支持 ...

  4. BZOJ.1013.[JSOI2008]球形空间产生器(高斯消元)

    题目链接 HDU3571 //824kb 40ms //HDU3571弱化版 跟那个一比这个太水了,练模板吧. //列出$n+1$个二次方程后两两相减,就都是一次方程了. #include <c ...

  5. CF1065E Side Transmutations

    link 题意: 给你一个长为m的序列$b_i$,定义两个字符串a,b相同当前仅当a执行以下操作后能变成b:($\rm{prefix}(x,y)$及$\rm{suffix}(x,y)$定义为串x的前/ ...

  6. mysql 日期 字符串 时间戳转换

    #时间转字符串 select date_format(now(), '%Y-%m-%d'); -02-27 #时间转时间戳 select unix_timestamp(now()); #字符串转时间 ...

  7. Android笔记之 网络http通信

    0.在认识HTTP前先认识URL 在我们认识HTTP之前,有必要先弄清楚URL的组成,比如: http://www.******.com/china/index.htm 它的含义例如以下: 1. ht ...

  8. cocos 主循环

    CCApplication的run为主循环,负责在空闲的时候,调用CCDirector的mainloop,setAnimationInterval设置多少秒一帧.m_nAnimationInterva ...

  9. [Winform]检测exe是否已经运行,并将其置顶

    摘要 在很多pc应用中,基本上都需要有这样的判断,保证在一个终端只运行一个winform的client.并且如果最小化了,用户再次双击桌面图标的时候,将client置顶显示. 解决方案 需要使用win ...

  10. android多设备界面适配的利器:属性weight的妙用

    1.按比例显示控件元素 <EditText android:id="@+id/edit_message" android:layout_weight="2" ...