深入理解NIO零拷贝

2021-12-12  本文已影响0人  jhon_11

NIO零拷贝

普通IO操作流程

image.png
  1. 用户程序向内核程序发起读请求
  2. cpu从用户模式切换到内核模式,内核模式向磁盘发出读取数据的请求
  3. 磁盘将数据读取到内核空间的缓冲区
  4. 内核将数据从缓冲区拷贝到用户空间的缓冲区
  5. 执行逻辑代码
  6. 执行write方法,将数据写到网络的另一端。
  7. 将数据从用户空间拷贝回内核空间
  8. 将数据真正的写到磁盘或者socket中
    这种方式会导致系统遇到瓶颈,为传统IO操作

零拷贝

零拷贝依赖于操作系统,操作系统实现了,则实现,没有实现则没有实现,跟java程序无关。


image.png
  1. 从图中可以看出对用户空间的数据拷贝已经没了。
  2. 内核空间收到sendfile()申请
  3. 内核空间向磁盘发送数据读取请求
  4. 磁盘将数据读取到内核空间缓冲区
  5. 将数据写入到socket缓冲区中
  6. 通过socket缓冲区向网络客户端发送数据
  7. 结果返回
  8. sendfile()调用返回
    这种操作我们称为零拷贝,相对与上一种情况有了极大的提升。
思考:

我们能不能减少磁盘拷贝到内核的情况,而是将磁盘数据直接拷贝到socket缓冲区中??

第二版零拷贝

image.png

这种方式实现了从磁盘空间直接读入Socket缓冲区

最终版零拷贝

image.png
  1. 用户程序发送sendfile()指令给内核空间并返回到用户空间
  2. 内核空间从磁盘采用DMA copy将数据从磁盘拷贝到了内核空间
  3. 将内核缓冲区的数据的文件描述符的信息拷贝到socketbuffer,而不是数据。文件描述中含有数据的内存地址等信息。
  4. protocol协议直接通过socketbuffer中读取到文件描述符信息从而找到kernel buffer存储数据的内存地址以及所需读取字符的长度。并将kernel buffer中的数据发送服务端

内存映射:

问题:上面的情况用户无法参与到数据的读取与写入的过程,如果用户需要参与呢??
内存映射文件:
通过代码的方式将文件映射到系统内核空间,这样修改文件只需要访问内核空间就可以。

参考

零拷贝学习
浅谈Linux下的零拷贝机制
mmap原理

上一篇下一篇

猜你喜欢

热点阅读