简介零复制(英语:Zero-copy;也译零拷贝)技术是指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。

零拷贝操作减少了在用户空间与内核空间之间切换模式的次数。

传统的I/O操作进行了3次用户空间与内核空间的上下文切换,以及4次数据拷贝。其中4次数据拷贝中包括了2次DMA拷贝和2次CPU拷贝。

Linux 中零拷贝技术的实现方向

一、直接 I/O

对于这种数据传输方式来说,应用程序可以直接访问硬件存储,操作系统内核只是辅助数据传输。这种方式依旧存在用户空间和内核空间的上下文切换,但是硬件上的数据不会拷贝一份到内核空间,而是直接拷贝至了用户空间,因此直接I/O不存在内核空间缓冲区和用户空间缓冲区之间的数据拷贝。

二、copy-on-write(写时复制技术)

在某些情况下,Linux操作系统的内核空间缓冲区可能被多个应用程序所共享,操作系统有可能会将用户空间缓冲区地址映射到内核空间缓存区中。当应用程序需要对共享的数据进行修改的时候,才需要真正地拷贝数据到应用程序的用户空间缓冲区中,并且对自己用户空间的缓冲区的数据进行修改不会影响到其他共享数据的应用程序。所以,如果应用程序不需要对数据进行任何修改的话,就不会存在数据从系统内核空间缓冲区拷贝到用户空间缓冲区的操作。

三、数据传输不经过用户进程地址空间

在数据传输的过程中,避免数据在操作系统内核地址空间的缓冲区和用户应用程序地址空间的缓冲区之间进行拷贝。有的时候,应用程序在数据进行传输的过程中不需要对数据进行访问,那么,将数据从 Linux 的页缓存拷贝到用户进程的缓冲区中就可以完全避免,传输的数据在页缓存中就可以得到处理。在某些特殊的情况下,这种零拷贝技术可以获得较好的性能。Linux 中提供类似的系统调用主要有 mmap(),sendfile() 以及 splice()。

mmap()1

2buf = mmap(diskfd, len);

write(sockfd, buf, len);

过程:

应用进程调用了 mmap() 之后,数据会先通过 DMA 拷贝到操作系统内核缓冲区中去。接着,应用进程跟操作系统共享这个缓冲区。这样,操作系统内核和应用进程存储空间就不需要再进行任何的数据拷贝操作。

应用进程再调用write(),操作系统直接将内核缓冲区的内容拷贝到socket缓冲区中,这一切都发生在内核态 。

socket缓冲区再把数据发到网卡。

使用 mmap 并不一定能获得理想的数据传输性能。数据传输的过程中仍然需要一次 CPU 拷贝操作,而且映射操作也是一个开销很大的虚拟存储操作,这种操作需要通过更改页表以及冲刷 TLB (使得 TLB 的内容无效)来维持存储的一致性。

sendfile()

为了简化用户接口,同时减少 CPU 的拷贝次数,Linux 在版本 2.1 中引入了 sendfile() 这个系统调用。

1ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);

过程:

sendfile() 系统调用利用 DMA 引擎将文件中的数据拷贝到操作系统内核缓冲区中。

然后数据被拷贝到与 socket 相关的内核缓冲区中去。

接下来,DMA 引擎将数据从内核 socket 缓冲区中拷贝到协议引擎中去。

sendfile() 系统调用不需要将数据拷贝或者映射到应用程序地址空间中去,所以 sendfile() 只是适用于应用程序地址空间不需要对所访问数据进行处理的情况。相对于 mmap() 方法来说,因为 sendfile 传输的数据没有越过用户应用程序 / 操作系统内核的边界线,所以 sendfile () 也极大地减少了存储管理的开销。

现在,已经减少了数据拷贝的次数,但是仍然存在一次CPU拷贝,就是页缓存到socket缓存的拷贝。

借助于硬件的帮助,可以把这个拷贝省略掉。即:

sendfile系统调用利用DMA引擎将文件内容拷贝到内核缓冲区去,然后将带有文件位置和长度信息的缓冲区描述符添加socket缓冲区去,这一步不会将内核中的数据拷贝到socket缓冲区中,DMA引擎会将内核缓冲区的数据拷贝到协议引擎中去,避免了最后一次拷贝。

splice()

splice() 可以被看成是类似于基于流的管道的实现,管道可以使得两个文件描述符相互连接,splice 的调用者则可以控制两个设备(或者协议栈)在操作系统内核中的相互连接。

1ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);

splice()在两个文件描述符之间移动数据,而不在内核地址空间和用户地址空间之间进行复制。它将文件描述符fd_in中的len个字节的数据传输到文件描述符fd_out,其中一个描述符必须引用一个管道。

如果fd_in引用一个管道,那么off_in必须为NULL。如果fd_in没有引用管道并且off_in为NULL,则从当前文件偏移量开始从fd_in读取字节,并且适当地调整当前文件偏移量。如果fd_in没有引用管道并且off_in不是NULL,那么off_in必须指向一个缓冲区,该缓冲区指定从fd_in读取字节的起始偏移量; 在这种情况下,fd_in的当前文件偏移量不会改变。类似的语句适用于fd_out和off_out。

flags参数是一个位掩码,它由零个或多个下列值组成:

1

2

3

4

5

6

7

8SPLICE_F_NONBLOCK: splice 操作不会被阻塞。然而,如果文件描述符没有被设置为不可被阻塞方式的 I/O

,那么调用 splice 有可能仍然被阻塞。

SPLICE_F_MORE: 告知操作系统内核下一个 splice 系统调用将会有更多的数据传来。

SPLICE_F_MOVE: 如果输出是文件,这个值则会使得操作系统内核尝试从输入管道缓冲区直接将数据读入

到输出地址空间,这个数据传输过程没有任何数据拷贝操作发生。如果内核不能从pipe

移动数据或者pipe的缓存不是一个整页面,仍然需要拷贝数据。

splice() 和 sendfile() 的区别与联系

联系:用户应用进程必须拥有两个已经打开的文件描述符,一个用于表示输入设备,一个用于表示输出设备。

区别:

1. splice() 允许任意两个文件之间互相连接

2. sendfile()只适用于文件到 socket 进行数据传输。

linux 零拷贝goodlen,linux零拷贝技术相关推荐

  1. Linux I/O原理和零拷贝Zero-copy技术全面揭秘

    目录 导言 计算机存储器 物理内存 虚拟内存 静态重定位 存储器抽象 交换(swapping)技术 虚拟内存技术 用户态和内核态 Linux I/O I/O 缓冲区 I/O 模式 程序控制 I/O 中 ...

  2. 零拷贝(Zero Copy)技术

    概念 我们知道Linux系统分为用户态和内核态,在用户态每发起一次IO请求,就需要进行2次上下文切换(分别是用户态->内核态,内核态→用户态),和一次CPU拷贝(将数据从内核缓存拷贝到用户缓存) ...

  3. SLAM导航机器人零基础实战系列:(一)Linux基础——2.安装Linux发行版ubuntu系统

    SLAM导航机器人零基础实战系列:(一)Linux基础--2.安装Linux发行版ubuntu系统 摘要 由于机器人SLAM.自动导航.语音交互这一系列算法都在机器人操作系统ROS中有很好的支持,所以 ...

  4. 视频教程-Linux零基础入门-Linux

    Linux零基础入门 毕业于解放军特种作战学院 曾就职某军区司令部,复原后从事IT行业,,具有独特的授课风格:思路清晰,语言简洁,讲解激情,幽默风趣,感染力强 李文瀚 ¥68.00 立即订阅 扫码下载 ...

  5. jdk+apache+jboss+mod_jk+openssl--从零开始搭建Linux测试环境

    http://blog.csdn.net/zhangren07/article/details/6269527 jdk+apache+jboss+mod_jk+openssl--从零开始搭建Linux ...

  6. 零基础学Linux内核之设备驱动篇(8)_设备模型

    零基础学Linux内核系列文章目录 前置知识篇 1. 进程 2. 线程 进程间通信篇 1. IPC概述 2. 信号 3. 消息传递 4. 同步 5. 共享内存区 编译相关篇 1. GCC编译 2. 静 ...

  7. 从零起步到Linux运维经理,你必须管好的23个细节

    2019独角兽企业重金招聘Python工程师标准>>> 从零起步到Linux运维经理,你必须管好的23个细节 双面人发表于热爱IT订阅 63 不想成为将军的士兵,不是好士兵-拿破仑 ...

  8. 【答学员问】我90年,零基础开始linux运维,算晚吗?

    写在前面: 博主是一名投身教培事业的标准八零后,叛逆而且追求自由,昵称取自于苏轼的<水调歌头>中的"高处不胜寒",时刻提醒自己要耐得住寂寞,受的了孤独,在技术的道路上, ...

  9. 零基础学Linux运维,看这一篇就够了(含30G自学教程笔记)

    作为一个10年老运维,在开始这篇文章之前,先送给大家一句话: 干啥不好,非要做运维,听人劝,吃饱饭,趁年轻,换行吧! 好了,不开玩笑了,回到正文中来. 当谈到运维职业发展情况时,很多人都会说运维做不长 ...

最新文章

  1. 【PC工具】简单好用的截屏gif录制小软件
  2. Linux C: IO库函数,文件流缓冲,变参函数
  3. 前端学习(2179):vue-router-router的由来和vue-router
  4. devtools的ctrl加r_Chrome DevTools调试技巧
  5. OFCMS 项目开源 java cms 系统 内容管理系统
  6. 大数据之-Hadoop3.x_MapReduce_自定义outputformat案例mapperreducer---大数据之hadoop3.x工作笔记0122
  7. 蓝桥杯2016年七届C/C++省赛C组第八题-冰雹数
  8. 一幅漫画趣味解读 Linux 内核
  9. IDEA 如果修改工作区的主题 也就是黑色背景和白色背景
  10. 深度学习教程(14) | 序列模型与RNN网络(吴恩达·完整版)
  11. springboot图片验证码
  12. String slices
  13. 好员工为什么离你而去
  14. PTA 7-6 新胖子公式
  15. 关闭Xshell系统提示音 Tab键 Backspace键
  16. Python第三方库巧用,制作图片验证码只需三行代码
  17. 服务器上部署java项目
  18. android 换肤 视频,网易云音乐4.0版体验:自定义换肤和短视频来了
  19. 如何解决Siri无法正常运行的问题
  20. 学习Vue的SSR,这可能是最好的教程

热门文章

  1. 二叉树的Morris遍历:先序遍历和中序遍历
  2. 新年争做金花王——今年守岁玩什么,短信金花任你游!
  3. strcasecmp()函数
  4. 简谈软件版本周期 | Alpha、Beta、RC、Stable版本之间的区别
  5. Java根据姓名生成头像(类似钉钉)
  6. Android 添加Calendar日历提醒事件
  7. MySQL数据库,分组函数篇
  8. Quicker中使用变量实现同一动作面板在不同设备上的不同配置
  9. LeetCode刷题记录——17电话号码的字母组合
  10. 短视频热点实时分享|想上热门你不能不知道的事