浅谈零拷贝


一、零拷贝

1.适用场景

应用程序从硬件设备读取和写入数据,都需要通过内核来进行交互。实际应用中会需要对来请求持久化到硬盘,或者从硬盘读取数据然后发送。整个操作过程中涉及到多次的数据复制和上下文切换。

2.零拷贝概念

零拷贝不是指没有进行数据拷贝,而是指减少需要CPU进行的数据拷贝,主要是为了释放CPU去执行其他任务。

3.零拷贝优点

  • 避免CPU数据拷贝,释放CPU去执行其他任务
  • 减少用户空间和内核空间上下文切换
  • 减少内存占用

二、传统IO-read/write

传统IO主要是应用程序用read系统调用进行数据读取,用write系统调用进行数据发送。相关函数如下:

#include <unistd>
ssize_t write(int filedes, void *buf, size_t nbytes);
ssize_t read(int filedes, void *buf, size_t nbytes);

在这里插入图片描述

1.数据读取过程

  • 应用进行read系统调用,导致从用户空间切换到内核空间
  • 内核线程等待DMA将数据从磁盘拷贝到内核缓冲区
  • 内核线程将数据从内核缓冲区拷贝到用户空间缓冲区
  • 内核线程返回read系统调用,导致内核空间切换到用户空间

2.数据发送过程

  • 应用进行write系统调用,导致从用户空间切换到内核空间
  • 内核线程将数据从用户空间缓冲区拷贝到socket缓冲区
  • 内核线程触发DMA将数据从socket缓冲区拷贝到网卡
  • 内核线程返回write系统调用,导致内核空间切换到用户空间

总结

整个操作过程涉及操作如下:

  • 四次用户空间与内核空间上下文切换
  • 两次CPU数据拷贝
  • 两次DMA数据拷贝

三、零拷贝-mmap/write

用mmap替换read函数,将用户缓冲区与内核缓冲区进行映射,减少CPU拷贝。相关函数如下:

#include <sys/mman.h>
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)

在这里插入图片描述

1.数据读取过程

  • 应用进行mmap系统调用,导致从用户空间切换到内核空间
  • 内核线程等待DMA将数据从磁盘拷贝到内核缓冲区
  • 内核线程将用户空间映射到内核缓冲区
  • 内核线程返回read系统调用,导致内核空间切换到用户空间

2.数据发送过程

  • 应用进行write系统调用,导致从用户空间切换到内核空间
  • 内核线程将数据从内核缓冲区拷贝到socket缓冲区
  • 内核线程触发DMA将数据从socket缓冲区拷贝到网卡
  • 内核线程返回write系统调用,导致内核空间切换到用户空间

总结

整个操作过程涉及操作如下:

  • 四次用户空间与内核空间上下文切换
  • 一次CPU数据拷贝,将用户空间映射到内核缓冲区减少一次CPU数据拷贝
  • 两次DMA数据拷贝

四、零拷贝-sendfile

这里是使用sendfile替换mmap/read+write函数调用,减少两次上下文切换。

#include <sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

在这里插入图片描述

1.执行过程

  • 应用进行senfile系统调用,导致从用户空间切换到内核空间
  • 内核线程等待DMA将数据从磁盘拷贝到内核缓冲区
  • 内核线程将数据从内核缓冲区拷贝到socket缓冲区
  • 内核线程触发DMA将数据从socket缓冲区拷贝到网卡
  • 内核线程返回senfile系统调用,导致内核空间切换到用户空间

总结

整个操作过程涉及操作如下:

  • 两次用户空间与内核空间上下文切换
  • 一次CPU数据拷贝
  • 两次DMA数据拷贝

五、零拷贝-sendfile(带DMA收集拷贝功能)

在这里插入图片描述

1.执行过程

  • 应用进行senfile系统调用,导致从用户空间切换到内核空间
  • 内核线程等待DMA将数据从磁盘拷贝到内核缓冲区
  • 内核线程将内核缓冲区描述符复制到socket缓冲区
  • 内核线程触发SG-DMA将根据描述符将数据从内核缓冲区拷贝到网卡
  • 内核线程返回senfile系统调用,导致内核空间切换到用户空间

总结

整个操作过程涉及操作如下:

  • 两次用户空间与内核空间上下文切换
  • 不需要CPU数据拷贝
  • 两次DMA数据拷贝

总结

零拷贝主要是通过Linux的不同函数,在数据读取和发送过程中,减少CPU参与的数据拷贝次数和上下文切换。


参考链接

1.小白也能秒懂的Linux零拷贝原理

  • 24
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值