看一遍就理解:零拷贝详解

44050097ef0d2b31c733aaedeb1be9c7.png

若有收获,请记得分享和转发哦

零拷贝是老生常谈的问题啦,大厂非常喜欢问。比如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缓冲区,最后写入网卡设备。

流程图如下:

86a410988fedb0ad07d76eec9a075718.png

e10abea8cc15b4e0e7c34c62bb739a09.png

d358094ec21a360ed32c7e147963f564.png

e248c329c30d81575879b3cb31bef015.png

46fca641046d266db7882dd95227ebf3.png

a16bd8b823ab3f6f135bf0e974bed326.png

ff68a57a2060c7bcdd3cb6ea1f278df3.png

452b6f48d4e56ba1f14250bb0e616a55.png

25ac4a8c8b1ea7cd5d52d4a0e573e70f.png

1d00338d32c64e8cb30a17d24f945fd9.png

546e0051f1d2ee2699410c90768b85a9.png

2cc295bf01e41b7dfbda93fac85deaa8.png

91ecc057781fe44c2de348dd45871ff5.png

bc7fb7d697566c3f2c64d34a3d95266c.png

81a195def291fa259060136cb5e66880.png

7a3d080a943d1f1bc44b713d561b840a.png

@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());
        }
    }
}
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值