Java 杂谈操作系统JAVA相关

深入理解NIO零拷贝及用户空间与内核空间切换

2019-05-15  本文已影响0人  爱学习的蹭蹭

1、什么是零拷贝

维基上是这么描述零拷贝的:零拷贝描述的是CPU不执行拷贝数据从一个存储区域到另一个存储区域的任务,这通常用于通过网络传输一个文件时以减少CPU周期和内存带宽。

2、零拷贝给我们带来的好处

3、 零拷贝的实现

4、传统I/O

1、JVM发出read() 系统调用。
2、OS上下文切换到内核模式(第一次上下文切换)并将数据读取到内核空间缓冲区。(第一次拷贝:hardware ----> kernel buffer)
3、OS内核然后将数据复制到用户空间缓冲区(第二次拷贝: kernel buffer --> user buffer),然后read系统调用返回。而系统调用的返回又会导致一次内核空间到用户空间的上下文切换(第二次上下文切换)。
4、JVM处理代码逻辑并发送write()系统调用。
5、OS上下文切换到内核模式(第三次上下文切换)并从用户空间缓冲区复制数据到内核空间缓冲区(第三次拷贝: user buffer ——> kernel buffer)。
6、write系统调用返回,导致内核空间到用户空间的再次上下文切换(第四次上下文切换)。将内核空间缓冲区中的数据写到hardware(第四次拷贝: kernel buffer ——> hardware)。

5、通过sendfile实现的零拷贝I/O

1、发出sendfile系统调用,导致用户空间到内核空间的上下文切换(第一次上下文切换)。通过DMA将磁盘文件中的内容拷贝到内核空间缓冲区中(第一次拷贝: hard driver ——> kernel buffer)。
2、然后再将数据从内核空间缓冲区拷贝到内核中与socket相关的缓冲区中(第二次拷贝: kernel buffer ——> socket buffer)。
3、sendfile系统调用返回,导致内核空间到用户空间的上下文切换(第二次上下文切换)。通过DMA引擎将内核空间socket缓冲区中的数据传递到协议引擎(第三次拷贝: socket buffer ——> protocol engine)。

6、带有DMA收集拷贝功能的sendfile实现的I/O

DMA

许多Web服务器都支持零拷贝,如Tomcat和Apache。 例如Apache的相关文档可以在这里找到,但默认情况下关闭。
注意:Java的NIO通过transferTo()提供了这个功能。

7 通过mmap实现的零拷贝I/O

通过mmap实现的零拷贝I/O进行了4次用户空间与内核空间的上下文切换,以及3次数据拷贝。其中3次数据拷贝中包括了2次DMA拷贝和1次CPU拷贝。明显,它与传统I/O相比仅仅少了1次内核空间缓冲区和用户空间缓冲区之间的CPU拷贝。这样的好处是,我们可以将整个文件或者整个文件的一部分映射到内存当中,用户直接对内存中对文件进行操作,然后是由操作系统来进行相关的页面请求并将内存的修改写入到文件当中。我们的应用程序只需要处理内存的数据,这样可以实现非常迅速的I/O操作。

8、NIO DirectByteBuffer

类名 类描述说明
HeapByteBuffer 堆缓冲区
DirectByteBuffer 直接缓冲区
MappedByteBuffer 映射缓冲区

HeapByteBuffer

DirectByteBuffer

MappedByteBuffer

9 总结

  • 零拷贝是操作系统底层的一种实现,我们在网络编程中,利用操作系统这一特性,可以大大提高数据传输的效率。这也是目前网络编程框架中都会采用的方式,理解好零拷贝,有助于我们进一步学习Netty等网络通信框架的底层原理。
  • 以上文章来自 Java NIO学习笔记四(零拷贝详解)进行个人整理
    推荐看堆外内存、零拷贝、DirectByteBuffer
上一篇 下一篇

猜你喜欢

热点阅读