• Linux 零拷贝splice函数


    Linux splice 函数简介

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

    函数原型

    #include 
    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:源文件的偏移量指针,在 fd_in 中的读取位置。可传入 NULL,表示使用当前位置。
    • fd_out:目标文件描述符,数据将写入到这个文件描述符中。
    • off_out:目标文件的偏移量指针,在 fd_out 中的写入位置。可传入 NULL,表示使用当前位置。
    • len:要传输的数据长度。
    • flags:传输标志位,可选参数,一般为 0。

    使用splice函数时,fd_in和fd_out必须至少有一个是管道文件描述符(局限)。splice函数调用成功时返回移动字节的数量。它可能返回0,表示没有数据需要移动,这发生在从管道中读取数据(fd_in是管道文件描述符)而该管道没有被写入任何数据时。splice函数失败时返回-1并设置errno。常见的errno如表6-3所示。

    1

    示例代码

    /**
     * 发送文件给客户端(splice版本)
     */
    int send_file_to_client(int client_fd, char *file)
    {
        int fd;
        struct stat fstat;
        int blocks, remain;
        int pipefd[2];
    
        fd = open(file, O_RDONLY);
        if (fd == -1) {
            return -1;
        }
    
        stat(file, &fstat);
    
        blocks = fstat.st_size / 4096;
        remain = fstat.st_size % 4096;
    
        pipe(pipefd);  // 创建管道作为中转
    
        for (i = 0; i < blocks; i++) {
            // 1. 将文件内容读取到管道
            splice(fd, NULL, pipefd[1], NULL, 4096, SPLICE_F_MOVE|SPLICE_F_MORE);
            // 2. 将管道的数据发送给客户端连接
            splice(pipefd[0], NULL, client_fd, NULL, 4096, SPLICE_F_MOVE|SPLICE_F_MORE);
        }
    
        if (remain > 0) {
            splice(fd, NULL, pipefd[1], NULL, remain, SPLICE_F_MOVE|SPLICE_F_MORE);
            splice(pipefd[0], NULL, client_fd, NULL, remain, SPLICE_F_MOVE|SPLICE_F_MORE);
        }
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    工作原理

    splice 函数的工作原理是在内核空间中直接操作页表,将数据从一个文件描述符传输到另一个文件描述符,避免了数据在用户空间和内核空间之间的复制。这样可以提高数据传输的效率。

    适用场景

    • 高效地将数据从一个文件描述符传输到另一个文件描述符,特别是在网络编程中可以提高数据传输的效率。
    • 需要避免在用户空间和内核空间之间频繁拷贝大量数据的情况下,提高性能。

    注意事项

    • splice 函数并不适用于所有情况,特别是在一些特定的文件系统或者设备上可能会有限制。
    • 适当的错误处理是必要的,特别是在文件描述符和偏移量的处理上需要小心。
    • 注意:使用splice函数时,fd_in和fd_out必须至少有一个是管道文件描述符。

    这就是关于 Linux 中 splice 函数的简要介绍。这个函数在一些特定场景下可以带来性能的提升,但使用时需要注意其适用性和一些限制。

    如果你想深入了解更多细节,可以查阅 Linux 手册或相关资料,以便更好地理解和使用这个函数。

  • 相关阅读:
    前端react 18.2整合ckeditor富文本编辑器——配置插件、自定义toolbar工具栏
    困惑了小白很久的问题——为什么Python列表和字典前面会加星号(**)?
    基于SSM的视频点播系统设计与实现
    多测师肖sir_高级讲师_第2个月第4讲python之判断循环语句
    每周统计-20240531
    git checkout到新的分支之后原来未提交的代码找回
    网络与VPC之动手实验
    Vue的生命周期
    设计模式-单例模式(最全总结)
    electron实现静默打印(各种踩坑解决)
  • 原文地址:https://blog.csdn.net/weixin_50448879/article/details/134497462