NIO的零拷贝的0指的是,0次需要cpu的拷贝,DMA拷贝不算在里面。零拷贝可以大大提高我们数据传输的效率。

传统IO

NIO之零拷贝

  • 磁盘 -> 内核空间的缓存
  • 内核空间的缓存 -> 用户态中的程序缓存
  • 对数据做一系列操作
  • 用户态中的程序缓存 -> 内核态的网卡内存
  • 网络发送(或拷贝到磁盘)!

在一次传统的IO中,操作系统一共进行了4次拷贝,4次操作系统状态转换

 注意,磁盘到内核态的读写是通过DMA拷贝,外部设备(磁盘,U盘)不通过CPU直接与系统内存交换数据。但是内核空间到用户空间需要CPU的参与与拷贝,需要进行状态切换
NIO之零拷贝

NIO 零拷贝

不需要对数据进行操作
windows Linux2.4以下

NIO之零拷贝

  • sendFile()
    该版本下的sendFile,只需要2次状态切换,即 开始: 用户态->内核态;拷贝结束:内核态->用户态,但是还需要把Read buffer中的数据通过cpu完整的拷贝到Socket Buffer,所以不能算是真正的0拷贝。

     该种方法是2次切换,1次拷贝
Linux 2.4以后

NIO之零拷贝

  • sendFile()
    该版本下,sendFile()直接将内核态的Read buffer发送到NIC的 buffer,只有部分描述信息经过socket buffer,再一次减少了数据拷贝(描述信息太少了,不算入拷贝次数中,所以是真正的0拷贝!)
需要对数据进行操作
  • mmap,把内核态的缓存空间和用户态的缓存空间映射到一块物理地址,实现共享,减少了内核态缓存到用户态缓存的一次拷贝。(因为使用mmap后,内存共享了,无需拷贝,但系统状态还是需要切换的)这样Read Buffer就可以直接将数据写入Socket Buffer。

     该种方法是3次状态切换,3次拷贝,相比传统的IO,少了一次从用户态缓存到内核态Socket buffer的拷贝(因为共享了嘛~)。

零拷贝的再次理解

  • 我们说零拷贝,是从操作系统的角度来说的。因为内核缓冲区之间,没有数据是重复的(只有kernel buffer有一份数据)。
  • )零拷贝不仅仅带来更少的数据复制,还能带来其他的性能优势,例如更少的上下文切换,更少的CPU缓存伪共享以及无CPU校验和计算。

mmap和sendFile的区别

  • mmap适合小数据读写, sendFile适合大文件传输
  • mmap需要4次上下文切换,3次数据拷贝;sendFile需要3次上下文切换,最小号2次数据拷贝
  • sendFile可以利用DMA,减少CPU拷贝,mmap则不能(必须从内核拷贝到Socket缓冲区)

参考
浅谈NIO与零拷贝
尚硅谷韩顺平Netty****(2019发布)

相关文章: