[转帖]Linux中的零拷贝技术

linux,拷贝,技术 · 浏览次数 : 0

小编点评

**内存映射** 内存映射是一种技术,可以让用户程序读取和修改共享内存的数据,就像读取用户空间自己的数据一样。无需由内核copy数据到用户空间。 **共享内存** 共享内存是一种技术,允许多个进程共享一个内存空间。数据可以从内核区复制到用户空间或从用户空间复制到内核空间。 **mmap内核和用户空间,共享内存** 当数据被复制到内核区后,应用程序可以使用mmap内核和用户空间共享内存来进行数据读写操作。这种技术可以减少数据复制的次数,提高效率。 **发送文件** 发送文件是一种技术,将数据从一个进程到另一个进程中传输。通常,这可以用于将数据从服务器上发送给客户端或从客户端上发送给服务器。 **sendfile内核和用户空间** sendfile内核和用户空间之间存在一个共享内存,该共享内存用于传输数据。 sendfile 函数从内核空间中读取数据并将其发送给用户空间,然后内核将该数据写入用户空间。

正文

https://www.jianshu.com/p/a757a93b6e5f

 

内存映射--mmap

内核和用户空间,共享内存。数据copy到内核区后,只需要把地址共享给应用程序即可,无需再copy一次数据到用户空间。

 
image.png

优点:

  • 用户程序可以读取和修改共享内存的数据,就像读取用户空间自己的数据一样。
  • 无需由内核copy数据到用户空间。

缺点:

  • 不支持和其他应用并发访问共享内存,会报非法访问错误

应用:
kafka生产者发送消息到broker的时候,broker的网络接收到数据后,copy到broker的内核空间。然后通过mmap技术,broker会修改消息头,添加一些元数据。所以,写入数据很快。当然顺序IO也是关键技术

sendFile

内核直接发送数据到socket,无需用户空间参与。

 
image.png

优点:

  • 无需把内核数据copy到用户空间

缺点:

  • 用户程序无法修改数据和读取数据,只能直接发送数据
  • 只能发送数据到socket

为了节省内核里面的一次copy,我们可以使用优化过的sendfile。该系统方法需要由特定的硬件来支持,并不是所有系统都支持。如下:


 
image.png

sendfile的时候,直接把内核空间的地址传递给socket缓存,DMA直接从指定地址读取数据到流里面。

splice

sendfile只适用于将数据从文件拷贝到套接字上,限定了它的使用范围。Linux在2.6.17版本引入splice系统调用,用于在两个文件描述符中移动数据。

#define _GNU_SOURCE         /* See feature_test_macros(7) */
#include <fcntl.h>
ssize_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,但是有一方必须是管道设备,这也是目前splice的一些局限性。flags参数有以下几种取值:

  • SPLICE_F_MOVE :尝试去移动数据而不是拷贝数据。这仅仅是对内核的一个小提示:如果内核不能从pipe移动数据或者pipe的缓存不是一个整页面,仍然需要拷贝数据。Linux最初的实现有些问题,所以从2.6.21开始这个选项不起作用,后面的Linux版本应该会实现。
  • SPLICE_F_NONBLOCK :splice 操作不会被阻塞。然而,如果文件描述符没有被设置为不可被阻塞方式的 I/O ,那么调用 splice 有可能仍然被阻塞。
  • SPLICE_F_MORE: 后面的splice调用会有更多的数据。

splice调用利用了Linux提出的管道缓冲区机制, 所以至少一个描述符要为管道。

以上几种零拷贝技术都是减少数据在用户空间和内核空间拷贝技术实现的,但是有些时候,数据必须在用户空间和内核空间之间拷贝。这时候,我们只能针对数据在用户空间和内核空间拷贝的时机上下功夫了。Linux通常利用写时复制(copy on write)来减少系统开销,这个技术又时常称作COW。

摘录网上:
传统的fork()系统调用直接把所有的资源复制给新创建的进程。这种实现过于简单并且效率低下,因为它拷贝的数据也许并不共享,更糟的情况是,如果新进程打算立即执行一个新的映像,那么所有的拷贝都将前功尽弃。Linux的fork()使用写时拷贝(copy-on-write)页实现。写时拷贝是一种可以推迟甚至免除拷贝数据的技术。内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝。只有在需要写入的时候,数据才会被复制,从而使各个进程拥有各自的拷贝。也就是说,资源的复制只有在需要写入的时候才进行,在此之前,只是以只读方式共享。这种技术使地址空间上的页的拷贝被推迟到实际发生写入的时候。在页根本不会被写入的情况下—举例来说,fork()后立即调用exec()—它们就无需复制了。fork()的实际开销就是复制父进程的页表以及给子进程创建惟一的进程描述符。在一般情况下,进程创建后都会马上运行一个可执行的文件,这种优化可以避免拷贝大量根本就不会被使用的数据(地址空间里常常包含数十兆的数据)。由于Unix强调进程快速执行的能力,所以这个优化是很重要的。这里补充一点:Linux COW与exec没有必然联系。

我总结下:copy-on-write技术其实是一种延迟复制的技术,只有需要用(写)的时候,才去复制数据。

与[转帖]Linux中的零拷贝技术相似的内容:

[转帖]Linux中的零拷贝技术

https://www.jianshu.com/p/a757a93b6e5f 内存映射--mmap 内核和用户空间,共享内存。数据copy到内核区后,只需要把地址共享给应用程序即可,无需再copy一次数据到用户空间。 image.png 优点: 用户程序可以读取和修改共享内存的数据,就像读取用户空间

[转帖]Linux中的grep -v、-e、-E用法小结

https://www.jb51.net/article/266590.htm grep是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来,这篇文章主要介绍了Linux之grep -v、-e、-E用法总结,需要的朋友可以参考下 + 目录 简介 grep (global sea

[转帖]Linux中的Grep命令(在文件中查找文本)

[日期:2020-05-14] 来源:Linux公社 作者:醉落红尘 [字体:大 中 小] grep命令是(global regular expression print,全局正则表达式输出)的缩写,它是Linux中功能最强大且最常用的命令之一。 grep在一个或多个输入文件中搜索与给定模式匹配的行

[转帖]Linux中的目录结构是什么样的?有人说像“树”,你觉得呢

https://bbs.huaweicloud.com/blogs/380543 【摘要】 在 Linux/Unix 操作系统中,一切都是文件,即使目录是文件,普通文件也是文件,鼠标、键盘、打印机等设备也是文件,本文笔者将带大家了解一下Linux中的文件目录结构。 文件类型Linux 中有三大类文件

[转帖]Linux中的用户和用户组

https://www.jianshu.com/p/76700505cac4 1,Linux中的用户分类 超级用户:拥有对系统的最高管理权限,默认是root用户。 普通用户:只能对自己目录下的文件进行访问和修改,具有登录到系统的权限。 虚拟用户:这类用户最大的特点就是不能登录系统,他们的存在主要是方

[转帖]Linux中的Page cache和Buffer cache详解

1、内存情况 在讲解Linux内存管理时已经提到,当你在Linux下频繁存取文件后,即使系统上没有运行许多程序,也会占用大量的物理内存。这是因为当你读写文件的时候,Linux内核为了提高读写的性能和速度,会将文件在内存中进行缓存,这部分内存就是Cache Memory(缓存内存)。即使你的程序运行结

[转帖]Linux中的inode到底是什么

https://www.jianshu.com/p/6aa4d7ef17de inode 是什么? 要了解 Linux 操作系统上的 inode 前,我们先来说说 Linux操作系统上的文件。对于 Linux 操作系统而言,[一切皆文件]。而文件是无法独立于存储介质(这里指的是物理磁盘或内存、闪存等

[转帖]Linux系统硬链接和软链接具体实例讲解(超详细)

简介 在 Linux 中,元数据中的 inode 号(inode 是文件元数据的一部分但其并不包含文件名,inode 号即索引节点号)才是文件的唯一标识而非文件名。文件名仅是为了方便人们的记忆和使用,系统或程序通过 inode 号寻找正确的文件数据块。而有一种方法可以快速的寻找到数据元,那就是软硬链

[转帖]Linux性能优化和内核观测 - 内存篇(一)

内存虚拟内存Linux 采用的是​​虚拟内存​​机制,每个进程都有自己的虚拟内存地址空间,仅当实际使用内存的时候才会映射到物理内存地址之上。这种设计提供了物理内存的超额分配,Linux 中的内存管理机制包括页换出守护进程(page out daemon)、物理换页设备(swap device),以及

[转帖]linux删除文本文件空白行

https://zhuanlan.zhihu.com/p/627152095 sed命令 在Linux中,可以使用sed命令批量删除文本中的空白行。以下是一个示例命令: sed -i '/^$/d' filename.txt 这个命令将会删除 filename.txt 文件中所有的空白行,并且直接在