linux内核零拷贝技术详解

1.前言

Linux系统中一切皆文件,仔细想一下Linux系统的很多活动无外乎读操作写操作,零拷贝就是为了提高读写性能而出现的。

2. 数据拷贝基础过程

在Linux系统内部缓存和内存容量都是有限的,更多的数据都是存储在磁盘中。对于Web服务器来说,经常需要从磁盘中读取数据到内存,然后再通过网卡传输给用户:

上述数据流转只是大框,接下来看看几种模式。

2.1 仅CPU方式
  • 当应用程序需要读取磁盘数据时,调用read()从用户态陷入内核态,read()这个系统调用最终由CPU来完成;
  • CPU向磁盘发起I/O请求,磁盘收到之后开始准备数据;
  • 磁盘将数据放到磁盘缓冲区之后,向CPU发起I/O中断,报告CPU数据已经Ready了;
  • CPU收到磁盘控制器的I/O中断之后,开始拷贝数据,完成之后read()返回,再从内核态切换到用户态;

2.2 CPU&DMA方式

CPU的时间宝贵,让它做杂活就是浪费资源。

直接内存访问(Direct Memory Access),是一种硬件设备绕开CPU独立直接访问内存的机制。所以DMA在一定程度上解放了CPU,把之前CPU的杂活让硬件直接自己做了,提高了CPU效率。

目前支持DMA的硬件包括:网卡、声卡、显卡、磁盘控制器等。

有了DMA的参与之后的流程发生了一些变化:

最主要的变化是,CPU不再和磁盘直接交互,而是DMA和磁盘交互并且将数据从磁盘缓冲区拷贝到内核缓冲区,之后的过程类似。

我们继续思考Web服务器读取本地磁盘文件数据再通过网络传输给用户的详细过程。

3.普通模式数据交互

一次完成的数据交互包括几个部分:系统调用syscall、CPU、DMA、网卡、磁盘等。

系统调用syscall是应用程序和内核交互的桥梁,每次进行调用/返回就会产生两次切换:

  • 调用syscall 从用户态切换到内核态
  • syscall返回 从内核态切换到用户态

来看下完整的数据拷贝过程简图:

读数据过程:

  • 应用程序要读取磁盘数据,调用read()函数从而实现用户态切换内核态,这是第1次状态切换;
  • DMA控制器将数据从磁盘拷贝到内核缓冲区,这是第1次DMA拷贝;
  • CPU将数据从内核缓冲区复制到用户缓冲区,这是第1次CPU拷贝;
  • CPU完成拷贝之后,read()函数返回实现用户态切换用户态,这是第2次状态切换;

写数据过程:

  • 应用程序要向网卡写数据,调用write()函数实现用户态切换内核态,这是第1次切换;
  • CPU将用户缓冲区数据拷贝到内核缓冲区,这是第1次CPU拷贝;
  • DMA控制器将数据从内核缓冲区复制到socket缓冲区,这是第1次DMA拷贝;
  • 完成拷贝之后,write()函数返回实现内核态切换用户态,这是第2次切换;

综上所述:

  • 读过程涉及2次空间切换、1次DMA拷贝、1次CPU拷贝;
  • 写过程涉及2次空间切换、1次DMA拷贝、1次CPU拷贝;

可见传统模式下,涉及多次空间切换和数据冗余拷贝,效率并不高,接下来就该零拷贝技术出场了。

4. 零拷贝技术

4.1 出现原因

我们可以看到,如果应用程序不对数据做修改,从内核缓冲区到用户缓冲区,再从用户缓冲区到内核缓冲区。两次数据拷贝都需要CPU的参与,并且涉及用户态与内核态的多次切换,加重了CPU负担。

我们需要降低冗余数据拷贝、解放CPU,这也就是零拷贝Zero-Copy技术。

4.2 解决思路

目前来看,零拷贝技术的几个实现手段包括:mmap+write、sendfile、sendfile+DMA收集、splice等。

4.2.1 mmap方式

mmap是Linux提供的一种内存映射文件的机制,它实现了将内核中读缓冲区地址与用户空间缓冲区地址进行映射,从而实现内核缓冲区与用户缓冲区的共享。

这样就减少了一次用户态和内核态的CPU拷贝,但是在内核空间内仍然有一次CPU拷贝。

mmap对大文件传输有一定优势,但是小文件可能出现碎片,并且在多个进程同时操作文件时可能产生引发coredump的signal。

4.2.2 sendfile方式

mmap+write方式有一定改进,但是由系统调用引起的状态切换并没有减少。

sendfile系统调用是在 Linux 内核2.1版本中被引入,它建立了两个文件之间的传输通道。

sendfile方式只使用一个函数就可以完成之前的read+write 和 mmap+write的功能,这样就少了2次状态切换,由于数据不经过用户缓冲区,因此该数据无法被修改。

从图中可以看到,应用程序只需要调用sendfile函数即可完成,只有2次状态切换、1次CPU拷贝、2次DMA拷贝。

但是sendfile在内核缓冲区和socket缓冲区仍然存在一次CPU拷贝,或许这个还可以优化。

4.2.3 sendfile+DMA收集

Linux 2.4 内核对 sendfile 系统调用进行优化,但是需要硬件DMA控制器的配合。

升级后的sendfile将内核空间缓冲区中对应的数据描述信息(文件描述符、地址偏移量等信息)记录到socket缓冲区中。

DMA控制器根据socket缓冲区中的地址和偏移量将数据从内核缓冲区拷贝到网卡中,从而省去了内核空间中仅剩1次CPU拷贝。

这种方式有2次状态切换、0次CPU拷贝、2次DMA拷贝,但是仍然无法对数据进行修改,并且需要硬件层面DMA的支持,并且sendfile只能将文件数据拷贝到socket描述符上,有一定的局限性。

4.2.4 splice方式

splice系统调用是Linux 在 2.6 版本引入的,其不需要硬件支持,并且不再限定于socket上,实现两个普通文件之间的数据零拷贝。

splice 系统调用可以在内核缓冲区和socket缓冲区之间建立管道来传输数据,避免了两者之间的 CPU 拷贝操作。

splice也有一些局限,它的两个文件描述符参数中有一个必须是管道设备。

5.本文小结

本文通过介绍数据交互的基本过程、传统模式的缺点,进而介绍了零拷贝的一些实现方法。

零拷贝技术是非常底层且重要的读写优化,对于服务并发能力的提升有很大帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/674168.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

linux系统上shell脚本编写问题总结

需求背景:项目技术栈:Vue2Nuxt2TypeScript,是一个服务端渲染的项目,每次打测试包时需要在虚拟机上通过命令行打包项目,然后将打包生成的文件压缩为一个压缩包.tar.gz,然后将这个压缩包下载到本地&#xff0…

免费API HUB行业报告

1. 行业概述 1.1 API HUB定义 API HUB,即应用程序接口中心,是一个集中管理和提供API服务的平台。它允许开发者轻松地访问和集成来自不同来源的API,从而加速开发过程并促进技术创新。 1.2 免费API HUB的特点 免费API HUB通常具有以下特点&…

免费听歌软件b端(但需要下载)

我会觉得很好用所以分享出来供大家使用。 这个事打开后的页面包括可以选择分页,和搜索等 回车可以用上面的搜索图片也可以点机 从前往后呢分别是排序,歌曲id,歌曲名称,歌手,专辑,歌曲长度,操作 …

【算法每日一练】新月轩就餐

思路: 其实很容易想到是双指针或者双端队列。 我们设置一个type表示当前区间已经有了多少种厨师,同时还需要记录区间中每个元素出现的次数,然后比较棘手的是移动问题了,什么时候移动呢? 我们可以发现当区间当队头元…

脂热控制+规律喝水+适量运动,健康减调全攻略

一、控制脂热的摄取量 肥胖大多都是因为身体摄取了多余的脂热而逐渐形成长成的,因此,控制脂热的摄取量就等于是控制了肥胖的涨幅。不了解的,按公式和例举的来就行 油脂量摄取公式:正常人每人每天油脂量摄取每公斤体重数x0.45&am…

【漏洞复现】海康威视综合安防管理平台 orgManage/v1/orgs/download 任意文件读取漏洞

0x01 产品简介 海康威视综合安防管理平台是一套“集成化”、“智能化”的平台,通过接入视频监控、一卡通、停车场、报警检测等系统的设备。海康威视集成化综合管理软件平台,可以对接入的视频监控点集中管理,实现统一部署、统一配置、统一管理和统一调度。 0x02 漏洞概述 海康…

算法学习笔记(7.4)-贪心算法(区间调度问题)

目录 ##什么是区间调度问题 ##贪心解法 ##具体的例题示例讲解 ##452. 用最少数量的箭引爆气球 - 力扣(LeetCode) ##435. 无重叠区间 - 力扣(LeetCode) ##56. 合并区间 - 力扣(LeetCode) ##什么是区间调…

【Go专家编程——语法糖】

语法糖 语法糖表示编程语言中特定类型的语法,这些语法对语言的功能没有影响,但是更方便程序员使用。 1.语法糖: 1.1 规则一:多变量复制可能会重新声明 我们知道可以使用“:”可以同时声明多个变量 field1, offset : nextField(str,0) fi…

重新安装VmWare的tools

原因: 因为一些原因,我需要重新安装VmWare tools,比如我升级到了win11,但是Vmware16.0已经不能使用,所以我升级了Vmware到16.2,这时候就需要升级VmWare tools。但是升级以后,会有一些小问题&…

MongoDB环境搭建

一.下载安装包 Download MongoDB Community Server | MongoDB 二、双击下载完成后的安装包开始安装,除了以下两个部分需要注意操作,其他直接next就行 三.可视化界面安装 下载MongoDB-compass,地址如下 MongoDB Compass Download (GUI) | M…

LabVIEW动态力传感器校准系统

LabVIEW动态力传感器校准系统 开发了一种基于LabVIEW的动态力传感器校准系统。系统主要用于动态力的测量和校准,通过高度集成化和自动化的设计,显著提升校准的效率和精确度。系统采用冲击法进行动态校准,涵盖了完整的硬件设计和软件开发流程…

SparkML

SparkML 一、介绍二、模型开发流程1、dataframe数据模型2、transformer转换器3、estimators模型学习器4、pipeline管道 三、示例:基于随机森林的新闻分类任务1、引入相关包2、初始化spark3、读取数据4、查看数据情况5、数据处理1、分词2、类别编码3、去除停用词4、b…

Python GNN图神经网络代码实战;GAT代码模版,简单套用,易于修改和提升,图注意力机制代码实战

1.GAT简介 GAT(Graph Attention Network)模型是一种用于图数据的深度学习模型,由Veličković等人在2018年提出。它通过自适应地在图中计算节点之间的注意力来学习节点之间的关系,并在节点表示中捕捉全局和局部信息。 GAT模型的核…

实现spring配置bean类机制

大家好,这里是教授.F 流程说明: 我们自己实现spring配置bean类的机制,要先了解原本是怎么实现的。 原本的机制就是有一个bean配置文件,还有一个ApplicationContext spring文件。bean类写着要扫描的文件信息,spring文…

vscode编译c/c++找不到jni.h文件

解决办法: 一、下载JDK 访问Oracle官网的Java下载页面:Java Downloads | Oracle 选择适合您操作系统的JDK版本: 对于Windows,选择“Windows x64”或“Windows x86”(取决于您的系统是64位还是32位)。对于Linux&#…

扩散世界模型已训练出赶超人类的智能体?

论文标题: Diffusion for World Modeling:Visual Details Matter in Atari 论文作者: Eloi Alonso, Adam Jelley, Vincent Micheli, Anssi Kanervisto, Amos Storkey, Tim Pearce, Franois Fleuret 项目地址: https://github.com/eloial…

封装了一个使用UICollectionViewLayout 实现的吸附居左banner图

首先查看效果图 实现的原理就是通过自定义UICollectionView layout,然后 设置减速速率是快速就可以达到吸附的效果 _collectionView.decelerationRate UIScrollViewDecelerationRateFast; 下面贴出所有代码 这里是.h // // LBMiddleExpandLayout.h // Liubo…

Java零基础-顺序结构

哈喽,各位小伙伴们,你们好呀,我是喵手。运营社区:C站/掘金/腾讯云;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一…

10 个最佳 MP4 转换器,可帮助您将视频转换为 MP4

许多人正在寻找一种强大的工具将视频转换为 MP4。网上有很多 MP4 转换器,但只有少数能够有效地将视频转换为 MP4。我们根据实验室测试和用户报告确定了前 10 名 MP4 转换器。在这篇文章中,我们将向您展示这些 MP4 转换器具有哪些功能以及如何使用它们。 …

【Python】 Python中的`mkdir -p`功能解析与应用

基本原理 在Linux系统中,mkdir -p是一个常用的命令,用于创建目录。这个命令的特点是,如果目标目录已经存在,它不会报错,而是直接跳过;如果目标目录不存在,它会创建整个目录路径中所需的所有目录…