值得注意的是,out_fd是待写入的文件描述符,必须是一个socket,而in_fd是待读出的文件描述符,但它必须指向真实的文件,不能使管道或者socket。我们用一个例子来看一下:

在上例中未在用户空间内申请任何缓冲区即完成了文件的传送,效率要比原始做法高得多。

splice函数用来在两个文件描述符间移动数据,也是零拷贝操作,但是其in_fd和out_fd中必须至少有一个管道文件描述符,调用成功时返回一共转移的字节数,以一个splice实现的简单回射服务器为例:

由于我们不能将数据从connfd的输入直接变成connfd的输出,所以我们借助了一个管道,将connfd的输入与管道的输入连接,将管道的输出与connfd的回射连接,这样就做成了一个高效率的回射服务器。
tee函数是在两个管道文件描述符之间复制数据,也是零拷贝操作,而它不消耗数据,原始数据仍可以用于后续操作,函数原型与返回值与splice类似,我们以一个可以同时输出数据到终端和文件的程序为例:
此程序有一个问题,使用splice将pipefd_stdout[0]连接到STDOUT_FILENO时出错,errno的值为EINVAL,在网上查了好久资料都没有收获,简单说一下我的看法:返回EINVAL的原因主要有四种,目标文件系统不支持splice,目标文件以追加方式打开,两个文件描述符都不是管道文件和某个offset参数被用于不支持随机访问的设备,而我们可以轻易排除1、3、4,标准输出文件默认应该是以追加方式打开的,这样在输出时才不会覆盖之前的数据,所以splice出错。
Linux提供了tee命令用于完成上述程序的操作,在tee函数的帮助文档里也有一个例子来完成上述操作,可用man 2 tee来查看。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-64695-2.html
这可是宙斯盾系统近1万顿的驱逐舰