大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
注意事项
(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
零拷贝
图片解读
- (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结果
图片分析
上图有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次数据拷贝,是真正意义上的零拷贝
参考
2018年最新深入netty 零基础到精通 张龙老师
https://mp.weixin.qq.com/s/dt0h2UhaoRECvjpeMZMsUA (☆)
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/191078.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...