0
点赞
收藏
分享

微信扫一扫

认识零拷贝

在觉 2022-09-16 阅读 162


注意事项

(1)零拷贝的含义是数据不从内核空间拷贝到用户空间,也不从用户空间拷贝到内核空间

(2)零拷贝完全依赖操作系统,操作系统提供了就是提供了,没有提供就没有提供,java本身做不了任何事情

传统的IO拷贝

需求

java读取磁盘上的文件,并且输出出去。这个过程包含两个步骤,一个是读,一个是写

图片解读

认识零拷贝_数据

三列分别为用户空间、内核空间、硬件

  • (1)read() syscall :java客户端(jvm虚拟机)向操作系统发起读磁盘数据的请求
  • (2)ask for data :系统向磁盘读数据
  • (3)data to kernel buffer through DMA: 磁盘数据通过DMA读到内核缓存区
  • (4)copy data to user buffer :把数据内核缓冲区复制到用户缓冲区(java堆)中
  • (5)code logic coutinues:业务逻辑处理
  • (6)wirte() syscall,copies data to kernel socket buffer:java客户端向系统发起写请求,并且把用户缓冲区(java堆)数据复制到内核缓冲区
  • (7)weites data:从内核缓冲区写到磁盘
  • (8)done:返回结果
  • (9)write() returns:返回写入结果

图片分析

上图有4次上下文切换:

(1)read() syscall :java客户端(jvm虚拟机)向操作系统发起读磁盘数据的请求  ----》从用户态切换为内核态

(4)copy data to user buffer :把数据内核缓冲区复制到用户缓冲区(java堆)中----》从内核态切换为用户态

(6)wirte() syscall,copies data to kernel socket buffer:java客户端向系统发起写请求,并且把用户缓冲区(java堆)数据复制到内核缓冲区----》从用户态切换为内核态

(9)write() returns:返回写入结果----》从内核态切换为用户态

上图有2次没有必要的数据拷贝(假设没有步骤5):

(4)copy data to user buffer :把数据内核缓冲区复制到用户缓冲区(java堆)中

(6)wirte() syscall,copies data to kernel socket buffer:java客户端向系统发起写请求,并且把用户缓冲区(java堆)数据复制到内核缓冲区

代码

InputStream 、OutputStream

​​Socket基础使用_CBeann的博客​​

零拷贝

图片解读 

  • (1)sendfile() syscall : java客户端(jvm虚拟机)向操作系统发起读磁盘数据sendfile的请求
  • (2)ask for data :系统向磁盘读数据
  • (3)data to kernel buffer through DMA: 磁盘数据通过DMA读到内核缓存区
  • (4)wirte data to target socket buffer:从内核空间缓冲区写到socket缓冲区
  • (5)writes data:socket向目标发送数据
  • (6)done:返回结果
  • (7) sendfile() returns :返回sendfile结果

认识零拷贝_数据_02

图片分析

上图有2次上下文切换(比传统的IO减少了2次切换):

(1)sendfile() syscall : java客户端(jvm虚拟机)向操作系统发起读磁盘数据sendfile的请求 ----》从用户态切换为内核态

(7) sendfile() returns :返回sendfile结果----》从内核态切换为用户态

上图有3次数据拷贝(比传统的IO减少了1次):

(3)data to kernel buffer through DMA: 磁盘数据通过DMA读到内核缓存区

(4)wirte data to target socket buffer:从内核空间缓冲区写到socket缓冲区

(5)writes data:socket向目标发送数据

代码

 fileChannel.transferTo(, , );
fileChannel.transferFrom(, , );

零拷贝升级版

升级版需要解决的问题:

上面零拷贝的第四步((4)从内核空间缓冲区写到socket缓冲区)是可以优化的

图片解读

看图片的下半部分:

看kernel buffer ---------------> socket buffer

Linux2.4之前的零拷贝是把 kernel buffer 中全部的数据 拷贝 到 socket buffer

Linux2.4之后的零拷贝是把kernel buffer中的地址和数据长度拷贝到到 socket buffer(优化后),类似

当真正发送数据的时候,客户端会从socketbuffer中拿到地址和数据长度找到kernel buffer 进行发送

这个过程只有2次数据拷贝,是真正意义上的零拷贝

认识零拷贝_数据_03

认识零拷贝_java_04

参考

2018年最新深入netty 零基础到精通 张龙老师

​​视频去哪了呢?_哔哩哔哩_bilibili​​

​​Netty、Kafka中的零拷贝技术到底有多牛?​​

​​https://mp.weixin.qq.com/s/dt0h2UhaoRECvjpeMZMsUA​​   (☆)

举报

相关推荐

0 条评论