若有收获,请记得分享和转发哦
零拷贝是老生常谈的问题啦,大厂非常喜欢问。比如Kafka为什么快,RocketMQ为什么快等,都涉及到零拷贝知识点。最近技术讨论群几个伙伴分享了阿里、虾皮的面试真题,也都涉及到零拷贝。因此本文将跟大家一起来学习零拷贝原理。
1. 什么是零拷贝
2. 传统的IO执行流程
3. 零拷贝相关的知识点回顾
4. 零拷贝实现的几种方式
5. java提供的零拷贝方式
1.什么是零拷贝
零拷贝字面上的意思包括两个,“零”和“拷贝”:
“拷贝”:就是指数据从一个存储区域转移到另一个存储区域。
“零” :表示次数为0,它表示拷贝数据的次数为0。
合起来,那零拷贝就是不需要将数据从一个存储区域复制到另一个存储区域咯。
零拷贝是指计算机执行IO操作时,CPU不需要将数据从一个存储区域复制到另一个存储区域,从而可以减少上下文切换以及CPU的拷贝时间。它是一种
I/O
操作优化技术。
2. 传统 IO 的执行流程
做服务端开发的小伙伴,文件下载功能应该实现过不少了吧。如果你实现的是一个web程序,前端请求过来,服务端的任务就是:将服务端主机磁盘中的文件从已连接的socket发出去。关键实现代码如下:
while((n = read(diskfd, buf, BUF_SIZE)) > 0)
write(sockfd, buf , n);
传统的IO流程,包括read和write的过程。
read
:把数据从磁盘读取到内核缓冲区,再拷贝到用户缓冲区write
:先把数据写入到socket缓冲区,最后写入网卡设备。
流程图如下:
@Override
public long transferFrom(FileChannel fileChannel, long position, long count) throws IOException {
return fileChannel.transferTo(position, count, socketChannel);
}
sendfile的小demo如下:
public class SendFileTest {
public static void main(String[] args) {
try {
FileChannel readChannel = FileChannel.open(Paths.get("./jay.txt"), StandardOpenOption.READ);
long len = readChannel.size();
long position = readChannel.position();
FileChannel writeChannel = FileChannel.open(Paths.get("./siting.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);
//数据传输
readChannel.transferTo(position, len, writeChannel);
readChannel.close();
writeChannel.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}