tee函数在两个管道文件之间复制数据,是零拷贝操作,它不消耗数据,因此源文件上的数据仍然可以用于后续操作.
函数原型:
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <fcntl.h>
ssize_t tee(int fd_in, int fd_out, size_t len, unsigned int flags);
code:
#include"../utili.h"
int main(int argc,char *argv[])
{
if(argc!=2)
{
printf("usage: %s <file>\n",argv[0]);
return 1;
}
int filefd = open(argv[1],O_CREAT|O_WRONLY|O_TRUNC,0666);
assert(filefd>0);
int pipefd_stdout[2];
int ret = pipe(pipefd_stdout);
assert(ret!=-1);
int pipefd_file[2];
ret = pipe(pipefd_file);
assert(ret!=-1);
ret = splice(STDIN_FILENO,NULL,pipefd_stdout[1],NULL,32768,SPLICE_F_MOVE|SPLICE_F_MORE);
assert(ret!=-1);
ret = tee(pipefd_stdout[0],pipefd_file[1],32768,SPLICE_F_NONBLOCK);
assert(ret!=-1);
ret = splice(pipefd_file[0],NULL,filefd,NULL,32768,SPLICE_F_MOVE|SPLICE_F_MORE);
assert(ret!=-1);
ret = splice(pipefd_stdout[0],NULL,STDOUT_FILENO,NULL,32768,SPLICE_F_MOVE|SPLICE_F_MORE);
assert(ret!=-1);
close(filefd);
close(pipefd_stdout[0]);
close(pipefd_stdout[1]);
close(pipefd_file[0]);
close(pipefd_file[1]);
return 0;
}
主要要理解这里的不消耗数据,所谓不消耗数据时说:比如上述代码中,从标准输入输入的数据,写入管道文件pipefd_stdout[1],,然后tee函数又从这个管道的读端将数据写入另外一个管道文件的写端,而后将数据从这个管道中输出到文件中,.之后又从pipefd_stdout的读端将数据写书标准输出. 即我们看到的tee 操作过后,仍旧可以从pipefd_stdout中读数据,也就是说tee操作没有消耗数据,可以对比的是如果用send函数操作管道文件描述符,读过的数据将不存在.
可以运行上述代码,可以看到文件中的数据和标准输出的数据完全相同