Linux网络编程 | 彻底搞懂零拷贝(zero-copy)技术

news2024/11/15 19:57:02

传统文件传输的问题

在网络编程中,如果我们想要提供文件传输的功能,最简单的方法就是用read将数据从磁盘上的文件中读取出来,再将其用write写入到socket中,通过网络协议发送给客户端。

ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);

但是就是这两个简单的操作,却带来了大量的性能丢失

例如我们的服务器需要为客户端提供一个下载操作,此时的操作如下

 

从上图可以看出,虽然仅仅只有这两行代码,但是却在发生了四次用户态和内核态的上下文切换,以及四次数据拷贝,也就是在这个地方产生了大量不必要的损耗。

那么为什么会发生这些操作呢?

上下文切换

由于read和recv是系统调用,所以每次调用该函数我们都需要从用户态切换至内核态,等待内核完成任务后再从内核态切换回用户态。

数据拷贝

上面也说了,由于数据的读取与写入都是由系统进行的,那么我们就得将数据从用户的缓冲区中拷贝到内核,

  • 第一次拷贝:将磁盘中的数据拷贝到内核的缓冲区中
  • 第二次拷贝:内核将数据处理完,接着拷贝到用户缓冲区中
  • 第三次拷贝:此时需要通过socket将数据发送出去,将用户缓冲区中的数据拷贝至内核中socket的缓冲区中
  • 第四次拷贝:把内核中socket缓冲区的数据拷贝到网卡的缓冲区中,通过网卡将数据发送出去。

所以要想优化传输性能,就要从减少数据拷贝和用户态内核态的上下文切换下手,这也就是零拷贝技术的由来。

什么是零拷贝呢?

零拷贝的主要任务就是避免CPU将数据从一块存储中拷贝到另一块存储,主要就是利用各种技术,避免让CPU做大量的数据拷贝任务,以此减少不必要的拷贝。或者借助其他的一些组件来完成简单的数据传输任务,让CPU解脱出来专注别的任务,使得系统资源的利用更加有效

Linux中实现零拷贝的方法主要有以下几种,下面一一对其进行介绍

  1. sendfile
  2. mmap
  3. splice
  4. tee

相关视频推荐

手写用户态协议栈以及零拷贝的实现

10道面试题搞清tcp/ip网络协议栈的秘密

【C++后端】2023年最新技术图谱,c++后端的8个技术维度,助力你快速成为大牛

免费学习地址:c/c++ linux服务器开发/后台架构师

需要C/C++ Linux服务器架构师学习资料加qun812855908获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

 

sendfile

sendfile函数的作用是直接在两个文件描述符之间传递数据。由于整个操作完全在内核中(直接从内核缓冲区拷贝到socket缓冲区),从而避免了内核缓冲区和用户缓冲区之间的数据拷贝。

需要注意的是,in_fd必须是一个支持类似mmap函数的文件描述符,不能是socket或者管道,而out_fd必须是一个socket,由此可见sendfile是专门为了在网络上传输文件而实现的函数。

 

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

参数: out_fd : 待写入内容的文件描述符 in_fd : 待读出内容的文件描述符 offset : 文件的偏移量 count : 需要传输的字节数 返回值: 成功:返回传输的字节数 失败:返回-1并设置errno

mmap

mmap用于申请一段内存空间,也就是我们在进程间通信中提到过的共享内存,通过将内核缓冲区的数据映射到用户空间中,两者通过共享缓冲区直接访问统一资源,此时内核与用户空间就不需要再进行任何的数据拷贝操作了

 其中mmap用于申请空间,额munmap用于释放这段空间。

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

参数:

addr : 内存的起始地址,如果设置为空则系统会自动分配

length : 指定内存段的长度

prot : 内存段的访问权限,通过按位与或可以取以下几种值

 flag : 选项

 fd : 被映射文件对应的文件描述符

offset : 文件的偏移量

返回值:

成功:成功时返回指向内存区域的指针

失败:返回MAP_FAILED并设置errno

splice

splice函数用于在两个文件描述符之间移动数据,而不需要数据在内核空间和用户空间中来回拷贝

需要注意的是,使用splice函数时fd_in和fd_out至少有一个是管道文件描述符,即

#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);

参数:

out_fd : 待写入内容的文件描述符

off_out : 待写入文件描述符的偏移量,如果文件描述符为管道则必须为空

in_fd : 待读出内容的文件描述符

off_in : 待读出文件描述符的偏移量,如果文件描述符为管道则必须为空

len : 需要复制的字节数

flags : 选项

 返回值:

成功:返回在两个文件描述符之间复制的字节数

没有数据:返回0

失败:返回-1并设置errno

可能产生的errno

 

tee

tee函数用于在两个管道文件描述符之间复制数据,并且它是直接复制,不会将数据读出,所以源文件上的数据仍可以用于后面的读操作

#include <fcntl.h>
ssize_t tee(int fd_in, int fd_out, size_t len, unsigned int flags);

参数:

out_fd : 待写入内容的文件描述符

in_fd : 待读出内容的文件描述符

len : 需要复制的字节数

flags : 选项

返回值:

成功:返回在两个文件描述符之间复制的字节数

没有数据:返回0

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JVM05 方法区

Person&#xff1a;存放在元空间&#xff0c;也可以说方法区 person&#xff1a;存放在Java栈的局部变量表中 new Person()&#xff1a;存放在Java堆中 1.方法区的理解 方法区主要存放的是 Class&#xff0c;而堆中主要存放的是 实例化的对象 方法区&#xff08;Method Area…

ubuntu清理挖矿病毒

0 序言 我之前搭建的hadoop用于测试&#xff0c;直接使用了8088和9870端口&#xff0c;没有放入docker&#xff0c;从而没有端口映射。于是&#xff0c;就被不法之徒盯上了&#xff0c;hadoop被提交了很多job&#xff0c;使得系统被感染了挖矿病毒&#xff0c;在前几天阿里云站…

企业实施了IM移动平台后,可以在上面做什么?

企业实施了IM移动平台后&#xff0c;可以有很多服务场景&#xff0c;其中员工服务平台是一个很好的场景组合。企业固然是以赢利为目的的组织&#xff0c;然而&#xff0c;在一个企业中同样需要有人文关怀的氛围。这种人文关怀&#xff0c;说到底&#xff0c;就是一种以员工为本…

阿里巴巴主流数据库连接池Druid入门

一.数据库连接池的必要性 (一).传统数据库连接模式的的步骤 1.在主程序中创建连接 2.进行sql操作 3.关闭数据库连接 &#xff08;二&#xff09;.传统数据库连接模式存在的问题 1.浪费时间&#xff1a;每次连接时都要验证登录和将conn加载到内存&#xff0c; 2.不能大规…

使用ThreadLocal实现当前登录信息的存取

有志者&#xff0c;事竟成 文章持续更新&#xff0c;可以关注【小奇JAVA面试】第一时间阅读&#xff0c;回复【资料】获取福利&#xff0c;回复【项目】获取项目源码&#xff0c;回复【简历模板】获取简历模板&#xff0c;回复【学习路线图】获取学习路线图。 文章目录一、使用…

【多线程与高并发】- 线程基础与状态

线程基础与状态 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 一个有梦有戏的人 怒放吧德德 &#x1f31d;分享学习心得&#xff0c;欢迎指正&#xff0c;大…

漏洞深度分析|CVE-2023-25141 sling-org-apache-sling-jcr-base存在JNDI注入漏洞

项目介绍 Apache Sling提供对可插入资源提供程序的支持。虽然这允许将自定义数据提供程序非常灵活和高效地集成到Sling中&#xff0c;但这种集成是在Sling的资源 API 级别上完成的。可能依赖于能够将资源适配到JCR节点并继续使用JCR API的遗留代码将不适用于此类资源提供者。 …

微信小程序自动化测试最佳实践(附 Python 源码)

目录&#xff1a;导读 小程序运行环境 微信小程序技术架构 使用 Chrome 调试小程序 小程序的性能测试 微信小程序的自动化测试​编辑 源码-微信小程序自动化测试 Python 版代码示例 小程序自动化测试需要跨过的几个坎 写在最后 随着微信小程序的功能和生态日益完善&…

“一号文件”聚焦三农,VR全景助农发展数字化

一号文件为何如此聚焦三农&#xff1f;因为三农是拼经济的基础&#xff0c;也是筑牢底盘的基本保证。现如今&#xff0c;农业基础还不稳固&#xff0c;而且城乡区域发展和居民收入差距依旧较大&#xff0c;为了解决城乡发展不平衡、农村发展不充分等矛盾&#xff0c;发展数字化…

Fuzz概述

文章目录AFL一些概念插桩与覆盖率边和块覆盖率afl自实现劫持汇编器clang内置覆盖率反馈与引导变异遗传算法fork server机制AFL调试准备AFL一些概念 插桩与覆盖率 边和块 首先&#xff0c;要明白边和块的定义 正方形的就是块&#xff0c;箭头表示边&#xff0c;边表示程序执行…

java有关类的初始化的分析

什么是类&#xff1f; 类是具有相同状态和相同行为的一组对象的集合 什么是对象&#xff1f; 万事万物皆为对象&#xff0c;可以理解为具体的个体就是对象 什么是面向对象的编程&#xff1f; 就是只在乎结果而不在乎过程&#xff0c;怎么理解这句话&#xff1f;举个例子&#x…

彻底废了,去干了两年外包...

先说一下自己的情况。大专生&#xff0c;17年通过校招进入湖南某软件公司&#xff0c;干了接近2年的点点点&#xff0c;今年年上旬&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落&#xff01;而我已经在一个企业干了五年的功能测试…

MacOS Ventura 13.2.1 (22D68) 正式版带 OC 0.8.9 and winPE 双分区原版黑苹果镜像

2 月 14 日消息&#xff0c;苹果今日向 Mac 电脑用户推送了 macOS 13.2.1 更新&#xff08;内部版本号&#xff1a;22D68&#xff09;&#xff0c;本次距离上次发布隔了 21 天&#xff0c;以修复Bug和安全更新为主。 镜像下载&#xff1a; 微信公众号&#xff1a; MacOS Vent…

docker 查看和分析镜像内文件

docker inspect docker inspect node:alpine查看元数据信息&#xff0c;一共有三层 "RootFS": {"Type": "layers","Layers": ["sha256:8c6806a0692459f603d074b4a7bdd38915650f1563f4ec728dad229475a52090","sha256:…

Python学习-----函数4.0(递归函数习题)

目录 递归算法 1.进制数转换 2.阶乘递归 3.递归获取两个数之间最小公倍数 4.递归获取两个数字之间最大公约数 5.斐波那契数列 5.递归求得数列的最值 6.倒序输出 7.递归二分法查找 递归算法 递归算法是把问题转化为规模缩小了的同类问题的子问题。然后递归调用函数(或过…

部署JDK+tomcat上线jspgou项目

系列文章目录 文章目录系列文章目录一、前言二、Tomcat部署1、Tomcat Http Server2、安装MySQL3、部署jspgou&#xff08;电子商城&#xff09;一、前言 什么是JAVA虚拟机 所谓虚拟机&#xff0c;就是一台虚拟的计算机。他是一款软件&#xff0c;用来执行一系列虚拟计算机指令…

背景透明(opacity vs background)

最近在做项目的时候&#xff0c;遇到透明度的相关设置。 常用的背景透明设置可分为两种&#xff0c;分别是&#xff1a; 一是给background设置透明度。二是利用opacity属性。 在跳了一些坑之后&#xff0c;本人更推荐给background设置透明度&#xff0c;为什么呢&#xff1f;…

【QCA6174】SDX12 WiFi QCA6174 bdwlan30.bin和bdwlan30.txt相互转化操作说明

1.从高通获bin文件和txt文件相互转化工具 软件包名称 QCA6174_BDF_Converter.zip 2.解压工具包&#xff0c;解压之后包括以下文件 3.从sdx12 sdk拷贝bdwlan30.bin 路径如下&#xff0c;将bdwlan30.bin放到QCA6174_BDF_Converter目录下 ./cnss_proc_firmware/cnss_proc/wlan…

Twitter账号老被封?一文教会你怎么养号

昨天龙哥给大家科普完要怎么批量注册Twitter账号&#xff0c;立刻有朋友来私信龙哥说里面提到的这个养号和防关联具体是个怎么样的做法。由于Twitter检测机制还是比较敏感的&#xff0c;账号很容易被冻结&#xff0c;所以养号是非常重要的步骤。其实要养好Twitter账号其实并不难…

docker-compose极速部署kafka3.2.0集群(含zookeeper集群)

极速部署kafka3.2.0集群准备工作&#xff1a;准备三台服务器部署Zookeeper集群部署kafka集群创建Topic开启JMX_PORTkafka集群管理工具使用的 KakfaStreaming准备工作&#xff1a;准备三台服务器 服务器地址缩写192.168.0.200200192.168.0.201201192.168.0.202202 一、完成服务…