【Linux编程】零拷贝之splice( )函数和tee( )函数
2015-12-10 00:18
1086 查看
关于零拷贝技术的相关文章,请参考:【Linux编程】大冒险之零拷贝技术探究
函数原型:
参数意义:
fdin参数:待读取数据的文件描述符。
offin参数:指示从输入数据的何处开始读取,为NULL表示从当前位置。如果fdin是一个管道描述符,则offin必须为NULL。
fdout参数:待写入数据的文件描述符。
offout参数:同offin,不过用于输出数据。
len参数:指定移动数据的长度。
flags参数:表示控制数据如何移动,可以为以下值的按位或:
SPLICE_F_MOVE:按整页内存移动数据,存在bug,自内核2.6.21后,实际上没有效果。
SPLICE_F_NONBLOCK:非阻塞splice操作,实际会受文件描述符本身阻塞状态影响。
SPLICE_F_MORE:提示内核:后续splice将调用更多数据。
SPLICE_F_GIFT:对splice没有效果。
fdin和fdout必须至少有一个是管道文件描述符。
返回值:
返回值>0:表示移动的字节数。
返回0:表示没有数据可以移动,如果从管道中读,表示管道中没有被写入数据。
返回-1;表示失败,并设置errno。
errno值如下:
EBADF:描述符有错。
EINVAL:目标文件不支持splice,或者目标文件以追加方式打开,或者两个文件描述符都不是管道描述符。
ENOMEM:内存不够。
ESPIPE:某个参数是管道描述符,但其偏移不是NULL。
函数原型:
参数意义:
fdin参数:待读取数据的文件描述符。
fdout参数:待写入数据的文件描述符。
len参数:表示复制的数据的长度。
flags参数:同splice( )函数。
fdin和fdout必须都是管道文件描述符。
返回值:
返回值>0:表示复制的字节数。
返回0:表示没有复制任何数据。
返回-1:表示失败,并设置errno。
为了简化操作,程序里省略了错误处理,实际编程中需要加入。
相关文件:
【Linux编程】大冒险之零拷贝技术探究
splice( )函数
在两个文件描述符之间移动数据,同sendfile( )函数一样,也是零拷贝。函数原型:
#include <fcntl.h> ssize_t splice(int fdin, loff_t *offin, int fdout, loff_t *offout, size_t len, unsigned int flags);
参数意义:
fdin参数:待读取数据的文件描述符。
offin参数:指示从输入数据的何处开始读取,为NULL表示从当前位置。如果fdin是一个管道描述符,则offin必须为NULL。
fdout参数:待写入数据的文件描述符。
offout参数:同offin,不过用于输出数据。
len参数:指定移动数据的长度。
flags参数:表示控制数据如何移动,可以为以下值的按位或:
SPLICE_F_MOVE:按整页内存移动数据,存在bug,自内核2.6.21后,实际上没有效果。
SPLICE_F_NONBLOCK:非阻塞splice操作,实际会受文件描述符本身阻塞状态影响。
SPLICE_F_MORE:提示内核:后续splice将调用更多数据。
SPLICE_F_GIFT:对splice没有效果。
fdin和fdout必须至少有一个是管道文件描述符。
返回值:
返回值>0:表示移动的字节数。
返回0:表示没有数据可以移动,如果从管道中读,表示管道中没有被写入数据。
返回-1;表示失败,并设置errno。
errno值如下:
EBADF:描述符有错。
EINVAL:目标文件不支持splice,或者目标文件以追加方式打开,或者两个文件描述符都不是管道描述符。
ENOMEM:内存不够。
ESPIPE:某个参数是管道描述符,但其偏移不是NULL。
tee( )函数
在两个管道文件描述符之间复制数据,同是零拷贝。但它不消耗数据,数据被操作之后,仍然可以用于后续操作。函数原型:
#include <fcntl.h> ssize_t tee(int fdin, int fdout, size_t len, unsigned int flags);
参数意义:
fdin参数:待读取数据的文件描述符。
fdout参数:待写入数据的文件描述符。
len参数:表示复制的数据的长度。
flags参数:同splice( )函数。
fdin和fdout必须都是管道文件描述符。
返回值:
返回值>0:表示复制的字节数。
返回0:表示没有复制任何数据。
返回-1:表示失败,并设置errno。
代码实例:
/*splice()和tee()实现将文件"./1.txt"同时拷贝到文件"./2.txt"和"./3.txt"中*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> int main(){ int fd1 = open("./1.txt", O_RDONLY); int fd2 = open("./2.txt", O_RDWR| O_CREAT | O_TRUNC, 0666); int fd3 = open("./3.txt", O_RDWR| O_CREAT | O_TRUNC, 0666); /*用于向"./2.txt"输入数据*/ int pipefd2[2]; /*用于向"./3.txt"输入数据*/ int pipefd3[2]; pipe(pipefd2); pipe(pipefd3); /*将fd1文件的内容输入管道pipefd2中*/ splice(fd1, NULL, pipefd2[1], NULL, 10086, SPLICE_F_MORE); /*将管道pipefd2的内容复制到管道pipefd3中,不消耗管道pipefd2上的数据,管道pipefd2上的数据可以用于后续操作*/ tee(pipefd2[0], pipefd3[1], 10086, SPLICE_F_NONBLOCK); /*将管道pipefd2的内容写入fd2文件中*/ splice(pipefd2[0], NULL, fd2, NULL, 10086, SPLICE_F_MORE); /*将管道pipefd3的内容写入fd3文件中*/ splice(pipefd3[0], NULL, fd3, NULL, 10086, SPLICE_F_MORE); close(fd1); close(fd2); close(fd3); close(pipefd2[0]); close(pipefd2[1]); close(pipefd3[0]); close(pipefd3[1]); return 0; }
为了简化操作,程序里省略了错误处理,实际编程中需要加入。
相关文件:
【Linux编程】大冒险之零拷贝技术探究
相关文章推荐
- Linux socket 初步
- linux lsof详解
- linux 文件权限
- Linux 执行数学运算
- 10 篇对初学者和专家都有用的 Linux 命令教程
- Linux 与 Windows 对UNICODE 的处理方式
- Ubuntu12.04下QQ完美走起啊!走起啊!有木有啊!
- 解決Linux下Android开发真机调试设备不被识别问题
- 运维入门
- 运维提升
- Linux 自检和 SystemTap
- Ubuntu Linux使用体验
- c语言实现hashmap(转载)
- Linux 信号signal处理机制
- linux下mysql添加用户
- Scientific Linux 5.5 图形安装教程
- 基于 Linux 集群环境上 GPFS 的问题诊断
- 谁是桌面王者?Win PK Linux三大镇山之宝
- vivi下重新调整分区