浅谈零拷贝


一、零拷贝

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零拷贝原理

相关推荐

  1. 结合场景,深浅度拷贝

    2024-03-14 09:12:04       9 阅读
  2. 拷贝拷贝

    2024-03-14 09:12:04       20 阅读
  3. 拷贝拷贝

    2024-03-14 09:12:04       16 阅读
  4. 拷贝拷贝

    2024-03-14 09:12:04       8 阅读
  5. 拷贝拷贝

    2024-03-14 09:12:04       11 阅读
  6. c++深拷贝拷贝

    2024-03-14 09:12:04       9 阅读
  7. 拷贝拷贝

    2024-03-14 09:12:04       8 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-14 09:12:04       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-14 09:12:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-14 09:12:04       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-14 09:12:04       20 阅读

热门阅读

  1. 鸿蒙 线程模型

    2024-03-14 09:12:04       19 阅读
  2. CMake在linux上的使用

    2024-03-14 09:12:04       22 阅读
  3. 什么是MVC

    2024-03-14 09:12:04       18 阅读
  4. InnoDB对MVCC的实现

    2024-03-14 09:12:04       20 阅读
  5. 事实分布式与价值集中式

    2024-03-14 09:12:04       21 阅读
  6. 并发编程2-掌握C#线程库的使用

    2024-03-14 09:12:04       20 阅读