linux高级I/O函数splice与tee

linux文件I/O: 高级I/O函数及其代码示例 注: man手册指出,in_fd必须是一个支持类似mmap函数的文件描述符,即它必须指向真实的文件,不能是socket和管道;splice函数可以在两个文件描述符之间移动数据,只在内核空间操作,不需要额外的缓冲区,适用于任意类型的文件描述符之间的数据传输,但至少有一个是管道。sendfile函数可以在两个文件描述符之间直接传输数据,不经过用户空间,减少了数据拷贝和上下文切换的开销,适用于从文件向网络发送数据的场景。readv将数据从文件描述符读到分散的内存块中,即分散读。 阅读详情

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

函数参数:

  • 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。

Linux高性能服务器编程|阅读笔记:第6章 - 高级I/O函数 Hello!ଘ(੭ˊᵕˋ)੭昵称:海轰标签:程序猿|C++选手|学生简介:因C语言结识编程,随后转入计算机专业,获得过国家奖学金,有幸在竞赛中拿过一些国奖、省奖…已保研学习经验:扎实基础 + 多做笔记 + 多敲代码 + 多思考 + 学好英语!唯有努力💪本文仅记录自己感兴趣的内容文章仅作为个人学习笔记记录,记录从0到1的一个过程希望对您有一点点帮助,如有错误欢迎小伙伴指正。 阅读详情

相关推荐

Allegro模块复用:从原理图到PCB的完整流程与关键细节

本文详细介绍了Allegro模块复用从原理图到PCB的完整流程与关键细节,包括DSN和MDD文件的创建、模块调用的实战技巧以及双向同步与版本控制方法。通过标准化处理和高级复用技巧,能显著提升PCB设计效率,减少重复工作时间。适用于智能硬件和工业控制等领域的工程师。

weixin_30252709的博客 332

Linux 零拷贝splice函数

splice是 Linux 系统中用于在两个文件描述符之间移动数据的系统调用。它的主要作用是在两个文件描述符之间传输数据,而无需在用户空间进行数据拷贝。也是零拷贝操作.

新法的博客 2787

[软考]系统架构设计师 备考经验分享(一) - 备考计划篇

前言 上周末刚刚结束了软考架构师的考试,自我感觉考的还可以,大概率是过了。 两次参加软考,一次中级嵌入式,一次高级架构师,都是备考不到两个月时间,尤其是架构师这次考试内容和本职工作有不小的差别,并且需要同时备考三个科目,在高强度地备考中感觉是摸索出到了一点软考的技巧与经验。 打算趁还记得,赶紧写几篇文章做下梳理总结,算是给将来自己考系分、高项或者其他考试做个记录,也希望能够帮到正在备考的大家。 先把第一步,个人的备考计划分享给大家。 自身情况分析 首先,请大家一定先明确三个问题,这三个问题会直接影响到你的

_ 6404

linux网络编程九:splice函数,高效的零拷贝

最近在看《linux高性能服务器编程》,在此做个日记,以激励自己,同时分享于有需要的朋友。 1. splice函数 #include ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags); splice用于在两个文件描述符之间移动数

JasonLiu的专栏 1万+

告别Vysor!用Scrcpy在Mac上无线投屏安卓手机(附魅族16th闪退修复实战)

本文详细介绍了如何在Mac上配置和使用开源投屏工具Scrcpy,实现安卓手机无线投屏的高效解决方案。从基础环境准备到高级功能调优,包括无线连接配置、输入控制增强、多设备管理和性能优化等实用技巧,特别针对魅族16th等机型的闪退问题提供了修复方案,帮助用户彻底告别Vysor等商业软件。

weixin_28712661的博客 394

基于STM32F407的立创球形六足双形态机器人:从Morphex复刻到毕业设计的完整开发指南

本文详细介绍了基于STM32F407主控芯片,从零开始复刻Morphex球形六足双形态机器人的完整开发过程。内容涵盖硬件选型(如总线舵机)、机械结构设计(阿基米德螺旋底盘)、软件控制(逆运动学与步态算法)以及多控制方式集成,为嵌入式系统与机器人开发的毕业设计或爱好者提供了全面的实战指南。

weixin_35414260的博客 321

linux内核splice方式实现零拷贝

如果off_in不是一个管道文件描述符(比如socket),那么off_in表示从输入数据流的何处开始读取数据,此时若为NULL,则从输入数据流的当前偏移位置读入。它可能返回0,表示没有数据需要移动,这通常发生在从管道中读数据(fd_in是管道文件描述符)而该管道没有被写入任何数据时。ESPIPE 参数fd_in(或fd_out)是管道文件描述符,而off_in(或off_out)不为NULL。fd_out/off_out参数的含义与fd_in/off_in相同,不过用于输出数据流。

大隐隐于野 1387

国科大学习资料--数据挖掘(刘莹)--第三章习题及参考答案

国科大学习资料–数据挖掘(刘莹)–第三章习题及参考答案 国科大学习资料–数据挖掘(刘莹)–第三章习题及参考答案 国科大学习资料–数据挖掘(刘莹)–第三章习题及参考答案 第 3 章分类与回归 3.1简述决策树分类的主要步骤。 答:决策树生成的过程如下: (1)对数据源进行数据预处理, 得到训练集和测试集; (2)对训练集进行训练; (3)对初始决策树进行树剪枝; (4)由所得到的决策树提取分类规则; (5)使用测试数据集进行预测,评估决策树模型; 3.2给定决策树,选项有:(1)将决策树转换成规则,然后对结果

无名何许人的博客 3090

浅析Linux中的零拷贝技术

http://www.jianshu.com/p/fad3339e3448 本文探讨Linux中主要的几种零拷贝技术以及零拷贝技术适用的场景。为了迅速建立起零拷贝的概念,我们拿一个常用的场景进行引入: 引文 在写一个服务端程序时(Web Server或者文件服务器),文件下载是一个基本功能。这时候服务端的任务是:将服务端主机磁盘中的文件不做修改地从已连接的socket发出去,

不积跬步无以至千里 873

CesiumForUnreal实现鹰眼地图(MiniMap)效果

CesiumForUnreal实现鹰眼地图(MiniMap)效果

专注GIS开发 3951

基于MUSIC算法的DOA估计Matlab仿真

特别需要指出的是:通道与阵元并不是一一对应,通道是由空间的一个、几个或所有阵元合成的,当然空间某个特定的阵元可包含在不同的通道内。空间谱估计侧重于研究空间多传感器阵列所构成的处理系统对感兴趣的空间信号的多种参数进行准确估计的能力,其主要目的是估计信号的空域参数或信源位置,这也是雷达、通信、声纳等许多领域的重要任务之一。从系统框图中可以清晰的看出,估计空间相当于是对目标空间的一个重构过程,这个重构的精度由众多因素决定,如环境的复杂性、空间阵元的互耦、通道不一致、频带不一致等。

FPGA/MATLAB学习教程/源码/项目合作开发 1747

从Linux零拷贝深入了解Linux-I/O

虽然这个技术的设计方案非常精彩,但是它的门槛和限制却不比前面介绍的其他技术少:首先会对操作系统 API 造成变动,需要使用新的一些 API 调用,其次还需要设备驱动程序配合改动,还有由于是内存共享,内核需要很小心谨慎地实现对这部分共享的内存进行数据保护和同步的机制,而这种并发的同步机制是非常容易出 bug 的从而又增加了内核的代码复杂度,等等。从前面的介绍可以看出,传统的 Linux I/O接口,都是基于复制/拷贝的:数据需要在操作系统内核空间和用户空间的缓冲区之间进行拷贝。

papaya的博客 569

边缘计算与产业生态系统

目录 文章目录目录边缘计算产业参与者边缘计算产业生态系统 边缘计算产业参与者 边缘计算领域参与者众多,主流公司以打造生态优势为目标,基于自身服务层级向产业链上下两端进行拓展,目前市场主要参与者有: 系统集成商:在产业头部,具有广泛的能力,可以集成不同生态系统公司的产品,具有一定的全球性属性,在边缘计算领域大多由云服务商、电信运营商担任。 云服务商:具有领先的云技术优势与应用生态体系,同时拥有全球性资源布局与市场资源生态,并渴望成为边缘计算主导者。 电信运营商:具有边缘基础设施优势,以及不可替代的

烟云的计算 2102

linux 高级i o函数,linux高級I/O函數splice與tee

splice()splice函數是linux系統提供的高級I/O函數,同sendfile系統調用函數一樣,也是零拷貝操作函數。splice函數用於在兩個文件描述符之間的移動數據。函數原型:#include ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t* off_out, size_t len, unsigned int f...

weixin_42377407的博客 136

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Linux中的高级IO函数(二)readv & writev & sendfile & mmap & splice & tee

Linux提供了很多高级的I/O函数。它们并不像Linux基础I/O函数(比如open和read)那么常用(编写内核模块时一般要实现这些I/O函数),但在特定的条件下却表现出优秀的性能。这些函数大致分为三类:用于创建文件描述符的函数,包括pipe、socketpair、dup/dup2函数。用于读写数据的函数,包括readv/writev、sendfile、mmap/munmap、splice和tee函数。用于控制I/O行为和属性的函数,包括fcntl函数。本节接着介绍第二类。

Lyajpunov的博客 1774

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

与网络相关Linux高级I/O函数

sendfile、 mmap、 splice、tee等Linux高级I/O函数 学习自:https://www.cnblogs.com/kex1n/p/7446291.html

WILLGOSPURS的博客 183

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

《Linux高性能服务器编程》学习总结(六)——高级I/O函数

第六章 高级I/O函数   网络I/O一直是Linux网络编程中极其重要的一部分,除了前面讲到的send、recv等,socket编程接口还给出了很多高级了I/O函数,这些函数大致分为三类:用于创建文件描述符的函数、用于读写控制的函数和用于控制I/O行为和属性的函数。   pipe函数是用来创建一个管道,管道是较为原始的进程间通信手段,分为无名管道和有名管道,而无名管道只能...

a5615024的博客 223

linux高性能服务器编程 (六) --高级I/O函数

第六章 高级I/O函数   Linux提供了很多高级的I/O函数,它不是基础的I/O函数(open/read)     1、创建文件描述符的函数比如:pipe、dup/dup2函数     2、读写数据的函数比如:readv/writev、sendfile、mmap/munmap、splice 和 tee 函数     3、控制 I/O 行为和属性的函数比如:fcntl 函数   pip...

weixin_30340353的博客 156

Linux高性能服务器编程 | 读书笔记 | 4. 高级 I/O 函数

函数,正如其名字(file control)描述的那样,提供了对文件描述符的各种控制,另一个常见的控制文件描述符属性和行为的系统调用是。最后,文件 B 的内核缓冲区中的数据会根据文件系统的要求和策略适时地被同步到磁盘上,完成文件 B 的更新。系统调用会在内核中建立一个直接从文件 A 的内核缓冲区(磁盘缓存)到文件 B 的内核缓冲区的通道。然后,数据直接从文件 A 的内核缓冲区通过内核内部的机制被传输到文件 B 的内核缓冲区。函数将文件 A 的内容传输到文件 B 时,数据是直接在内核空间中进行转移的。

m0_74795952的博客 1239

网络编程API-中 (高级I/O函数)

pipe函数 #include int pipe(int fd[2]); 返回:成功返回0,并将一对打开的文件描述符值填入其参数指向的数组,出错0

luoxn28的专栏 1250

《Linux高性能服务器编程》学习笔记——第六章 高级I/O函数

Linux高级I/O函数在特定条件下有相当优秀的性能。   1、pipe函数 pipe函数用于创建一个管道,实现进程间的通信: #include int pipe(int fd[2]); 函数成功返回0,并将打开的一对文件描述符填入参数数组。失败返回-1并设置errno。 通过pipe函数创建的文件描述符fd[0]和fd[1]分别构成管道的两端,往fd[1]写入的数据可以从

爱很遥远 667

Linux的高性能服务器编程 高级I/O函数总结

dup和dup2是Linux系统中用于复制文件描述符的函数,允许不同文件描述符共享同一文件。dup复制现有描述符并返回新描述符,而dup2则直接指定新描述符,若已打开则先关闭。readv和writev函数通过减少系统调用和内存拷贝提高数据传输效率,适用于处理多个小数据块。sendfile和splice函数则通过内核空间直接传输数据,减少数据复制和上下文切换,特别适合大文件或大量数据传输。fcntl函数用于控制文件描述符的属性,如文件锁定等。这些函数和工具在Linux系统编程中广泛用于提高文件操作和数据传输的

2301_80140457的博客 1039

高级I/O函数(二)

本篇文章到这里就结束了!!!高级IO编程就到这里结束了,希望可以帮助大家理解~~~

2503_93247646的博客 347

Linux高性能服务器编程第六章——高级I/O函数 学习笔记

linux高性能服务器编程ch6关于io操作的函数,创建文件描述符、输入输出、控制属性。

m0_57222081的博客 388

高级IO函数

prot 设置访问权限,取值为 PROT_READ(可读)、PROT_WRITE(可写)、PROT_EXEC(可执行)、PROT_NONE(不能被访问) 这几个值的按位或;(2)输出,默认情况下,调试信息会保持到 /var/log/debug 中,普通信息到 /var/log/messages,内核消息到 /var/log/kern.log;中 pid 为 0,表示设置当前进程的 PGID 为 pgid;,会使得调用进程成为会话的首领,会新建一个进程组,调用进程成为该组首领,调用进程将甩开终端;

weixin_44835655的博客 171
上一篇: linux高级I/O函数sendfile
下一篇: c++关联容器总结
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值