linux内核splice方式实现零拷贝

splice()
splice函数是linux系统提供的高级I/O函数,同sendfile系统调用函数一样,也是零拷贝操作函数。splice函数用于在两个文件描述符之间的移动数据。

函数原型:
#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);  
1
2
函数参数:
fd_in参数是待输入描述符。如果它是一个管道文件描述符,则off_in必须设置为NULL;如果off_in不是一个管道文件描述符(比如socket),那么off_in表示从输入数据流的何处开始读取数据,此时若为NULL,则从输入数据流的当前偏移位置读入。
fd_out/off_out参数的含义与fd_in/off_in相同,不过用于输出数据流。
len参数指定移动数据的长度。
flags参数则控制数据如何移动,它可以设置成下表中的某些值的按位或。
splice的flags参数的常用值及其含义:

常用值    含义
SPLICE_F_MOVE    如果合适的话,按整页内存移动数据。这只是给内核的一个提示。不过,因为它的实现存在BUG,所以自内核2.6.21后,它实际上没有任何效果
SPLICE_F_NONBLOCK    非阻塞的splice操作,但实际效果还会受文件描述符本身的阻塞状态影响
SPLICE_F_MORE    告知操作系统内核下一个 splice 系统调用将会有更多的数据传来
SPLICE_F_GIFT    对splice没有效果
注意:使用splice函数时,fd_in和fd_out必须至少有一个是管道文件描述符。

函数返回值:
调用成功时返回移动的字节数量。它可能返回0,表示没有数据需要移动,这通常发生在从管道中读数据(fd_in是管道文件描述符)而该管道没有被写入任何数据时。
失败时返回-1,并设置errno。常见的errno如下表所示。

splice函数可能产生的errno及其含义:

错误    含义
EBADF    参数所指文件描述符有错
EINVAL    目标文件系统不支持splice,或者目标文件以追加方式打开,或者两个文件描述符都不是管道文件描述符,或者某个offset参数被用于不支持随机访问的设备(比如字符设备)
ENOMEM    内存不够
ESPIPE    参数fd_in(或fd_out)是管道文件描述符,而off_in(或off_out)不为NULL
使用splice函数实现简单的回射服务器:
我们通过使用splice函数,实现一个简单的echo服务器。

//使用splice实现的回显服务器  
#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <assert.h>  
#include <errno.h>  
#include <string.h>  
#include <fcntl.h>  


int main(int argc, char **argv)  
{  

    if (argc <= 2) {  
        printf("usage: %s ip port\n", basename(argv[0]));  
        return 1;  
    }  

    const char *ip = argv[1];  
    int port = atoi(argv[2]);  

    struct sockaddr_in address;  
    bzero(&address, sizeof(address));  
    address.sin_family = AF_INET;  
    address.sin_port = htons(port);  
    inet_pton(AF_INET, ip, &address.sin_addr);  

    int sock = socket(PF_INET, SOCK_STREAM, 0);  
    assert(sock >= 0);  

    int reuse = 1;  
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));  

    int ret = bind(sock, (struct sockaddr*)&address, sizeof(address));  
    assert(ret != -1);  

    ret = listen(sock, 5);  
    assert(ret != -1);  

    struct sockaddr_in client;  
    socklen_t client_addrlength = sizeof(client);  

    int connfd = accept(sock, (struct sockaddr*)&client, &client_addrlength);  
    if (connfd < 0) {  
        printf("errno is: %s\n", strerror(errno));  
    }  
    else {  
        int pipefd[2];  

        ret = pipe(pipefd);  //创建管道  
        assert(ret != -1);  

        //将connfd上流入的客户端数据定向到管道中  
        ret = splice(connfd, NULL, pipefd[1], NULL,  
                        32768, SPLICE_F_MORE | SPLICE_F_MOVE);  
        assert(ret != -1);  

        //将管道的输出定向到connfd连接文件符上  
        ret = splice(pipefd[0], NULL, connfd, NULL,  
                        32768, SPLICE_F_MORE | SPLICE_F_MOVE);  
        assert(ret != -1);                

        close(connfd);  
    }  

    close(sock);  

    return 0;  


tee()
tee函数在两个管道文件描述符之间复制数据,也是零拷贝操作。与splice函数不同,它不消耗数据,因此源文件描述符上的数据仍然可以用于后续的读操作。

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

函数参数:
该函数的参数含义与splice相同(但fd_in和fd_out必须都是管道文件描述符)。

函数返回值:
tee函数成功时返回在两个文件描述符之间复制的数据数量(字节数)。返回0表示没有复制任何数据。tee失败时返回-1并设置errno。

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

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

相关文章

免费SSL证书的安全性与获取指南

SSL证书是一种数字凭证&#xff0c;用于加密用户与网站之间的信息交换&#xff0c;以确保传输的数据不被第三方窃取。它像是一个数字版的密封印章&#xff0c;为数据的传输过程提供了一层保护膜。 免费的SSL证书通常由CA机构提供&#xff0c;它们同样可以提供基础数据的加密服…

16.Redis之Redis事务

1.MySQL 事务 原子性: 把多个操作,打包成一个整体了 一致性: 事务执行之前,和之后,数据都不能离谱~ 持久性: 事务中做出的修改都会存硬盘 隔离性: 事务并发执行,涉及到的一些问题~~ 2.Redis事务 2.1 认识Redis事务 • 弱化的原⼦性: redis 没有 "回滚机制". …

14、matlab中矩阵的赋值、调用、运算、范数和距离计算

1、矩阵赋值 1&#xff09;直接输入参数 代码&#xff1a; A[1 2 3 4 5;2 3 4 5 6]%矩阵赋值A 1 2 3 4 52 3 4 5 6 2)全一矩阵 代码&#xff1a; Cones(3:3)%全1矩阵C 1 1 11 1 11 1 1 3&#xff09;全零矩阵 …

.NET最新漏洞 | 某SLMS系统存在SQL注入

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

翻译《The Old New Thing》- How do I force the ECHO command to echo?

How do I force the ECHO command to echo? - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20080403-00/?p22883 Raymond Chen 2008年04月03日 如何强制执行ECHO命令以进行回显&#xff1f; 简要 ECHO命令用于在命令行打印文本&#xff0…

统一预订,YonSuite商旅费控助力成长型企业“消灭报销”

在成长型企业快速发展的道路上&#xff0c;商旅管理作为连接企业内外的重要纽带&#xff0c;其效率与成本直接影响着企业的整体运营。面对日益增长的商旅需求&#xff0c;如何简化预订流程、降低管理成本、提高运营效率成为了成长型企业亟待解决的问题。用友YonSuite商旅费控以…

【权威出版】2024年新媒体、网络与电子商务国际会议(NMNE 2024)

2024年新媒体、网络与电子商务国际会议 2024 International Conference on New Media, Networking, and E-commerce 【1】会议简介 2024年新媒体、网络与电子商务国际会议即将召开&#xff0c;这是一次集结全球新媒体、网络与电子商务领域精英的学术盛会。 本次会议将深…

DPDK基础组件一(mbuf、ring、pktmbuf_pool)

一、rte_mbuf 此部分转自:https://zhuanlan.zhihu.com/p/616314276 1.mbuf结构 mbuf是报文中的描素的结构体,是整个转发过程中最核心的数据结构之一。主要针对于mbuf的常用API与基本原理做一个简单的介绍。 mbuf:报文内存存储结构,存储在mempool中mempool:使用环形缓冲…

Latex中论文常用的符号、公式、引用格式

内容符号 波浪号 ~&#xff1a;$ \sim $加减号 &#xff1a;$ \pm$点 &#xff1a;$ \cdot $乘号 ∗&#xff1a;$ \ast $约等于 ≈&#xff1a;$ \approx $≤ : $ \le $≥ : $ \ge $ 数学表示 下箭头 ↓ \downarrow ↓ &#xff1a;$ \downarrow $上箭头 ↑ \uparrow ↑: $…

Web安全:软件开发的安全问题与解决方案

「作者简介」&#xff1a;2022年北京冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础对安全知识体系进行总结与归纳&#xff0c;著作适用于快速入门的 《网络安全自学教程》&#xff0c;内容涵盖系统安全、信息收集等…

第三站:Java红——异常处理的热情与挑战

### 第三站&#xff1a;Java红——异常处理的热情与挑战 在Java编程的征途中&#xff0c;异常处理是无法绕过的“红色地带”&#xff0c;它充满了挑战&#xff0c;也饱含解决问题的热情。通过合理地使用异常处理机制&#xff0c;我们可以编写出更加健壮、容错性强的代码。本节…

jni调用so或dll区别

在Java中通过JNI&#xff08;Java Native Interface&#xff09;调用本地代码时&#xff0c;所使用的动态库文件扩展名&#xff08;如 .dll 对于Windows或 .so 对于Unix-like系统&#xff09;取决于你的操作系统和目标平台。 DLL&#xff08;Dynamic Link Library&#xff09;…

python数据预处理

PYTHON 最流行库&#xff1a;Numpy、Matplotlib 和 Pandas。Numpy 是满足所有数学运算所需要的库&#xff0c;由于代码是基于数学公式运行的&#xff0c;因此就会使用到它。Maplotlib&#xff08;具体而言&#xff0c;Matplotlib.pyplot&#xff09;则是满足绘图所需要的库。Pa…

使用redis的setnx实现分布式锁

在Redis中&#xff0c;SETNX 是 “Set If Not Exists”&#xff08;如果不存在&#xff0c;则设置&#xff09;的缩写。这是一个原子操作&#xff0c;用于设置一个键的值&#xff0c;前提是这个键不存在。如果键已经存在,.则不会执行任何操作。 封装方法trylock&#xff0c;用…

智能超越了科技,更是一个复杂系统

智能不仅仅是科技系统&#xff0c;更是一个复杂系统。智能是一个多学科领域&#xff0c;涉及计算机科学、人工智能、神经科学、心理学、社会学、人文艺术、宗教哲学等多个学科。科技系统只是智能的一部分&#xff0c;虽然它们在处理信息和执行任务方面非常强大&#xff0c;但它…

CCF-CSP认证 2023年3月01 田地丈量

矩形重叠面积公式&#xff1a; p1与p2表示矩形A的左下角和右上角&#xff0c;用p3和p4表示矩形B的左下角和右上角。 res!(p1.x > p4.x) || (p2.x < p3.x) || (p1.y > p4.y) || (p2.y < p3.y) //对矩阵不重叠求反 矩阵重叠面积 double Len Math.min(p2_x, p4_x…

深入解析Solon路由的Url大小写匹配策略与实际应用

在数字化时代的背景下&#xff0c;企业对于采购管理的需求日益增长。为了满足这一需求&#xff0c;我们通过采用Spring Cloud、Spring Boot2、Mybatis等先进技术&#xff0c;构建了一个从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理平台。 Solon路由器对ur…

小米员工自爆:35岁被裁后,投百份简历无人问津,一气之下把薪资由2W调为3W,简历改成英文,结果出乎意料

“35岁”&#xff0c;就像职场里一道无形的门槛&#xff0c;压得人喘不过气。一旦迈过这道坎&#xff0c;焦虑、迷茫、恐慌&#xff0c;接踵而至。 最近&#xff0c;我的朋友老张&#xff0c;就真切地体会到了这种“中年危机”。刚过36岁生日&#xff0c;他就收到了来自小米的裁…

从0到1写一个vue2项目,按需引入element-ui的引入,npm下载路由,配置路由,路由嵌套

从0到1写一个vue2项目&#xff0c;此篇内容有element-ui的按需引入&#xff0c;npm下载路由&#xff0c;配置路由&#xff0c;路由嵌套 项目是b站上找的项目链接在此https://www.bilibili.com/video/BV1QU4y1E7qo/?p8&spm_id_frompageDriver&vd_source2c599bf1d75e3f9…

Hive之聚合类开窗函数 + 滑动求和

为什么要写这样子一个主题文章呢&#xff0c;开窗函数毫无疑问&#xff0c;超级重要&#xff0c;但是很多人可能不会遇到一些稍微小众的业务需求&#xff0c;比如说滑动求和。这里带着业务&#xff0c;一并让大家熟悉一些&#xff0c;高阶函数的应用。 0&#xff0c;开窗函数和…