Linux splice()返回EINVAL(“无效参数") [英] Linux splice() returning EINVAL ("Invalid argument")
问题描述
I'm trying to experiment with using splice (man 2 splice) to copy data from a UDP socket directly to a file. Unfortunately the first call to splice() returns EINVAL.
该手册页指出:
EINVAL Target file system doesn't support splicing; target file is opened in
append mode; neither of the descriptors refers to a pipe; or offset
given for nonseekable device.
但是,我认为这些条件均不适用.我正在使用Fedora 15(内核2.6.40-4),因此我相信所有文件系统都支持splice().在第一次调用拼接文件时,目标文件应该无关紧要,但是为了完整起见,我通过open(path, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR)
打开它.这两个调用都使用管道,并且两个调用都没有使用NULL以外的偏移量.
However, I believe none of those conditions apply. I'm using Fedora 15 (kernel 2.6.40-4) so I believe splice() is supported on all filesystems. The target file should be irrelevant in the first call to splice, but for completeness I'm opening it via open(path, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR)
. Both calls use a pipe and neither call uses an offset besides NULL.
这是我的示例代码:
int sz = splice(sock_fd, 0, mPipeFds[1], 0, 8192, SPLICE_F_MORE);
if (-1 == sz)
{
int err = errno;
LOG4CXX_ERROR(spLogger, "splice from: " << strerror(err));
return 0;
}
sz = splice(mPipeFds[0], 0, file_fd, 0, sz, SPLICE_F_MORE);
if (-1 == sz)
{
int err = errno;
LOG4CXX_ERROR(spLogger, "splice to: " << strerror(err));
}
return 0;
sock_fd由以下伪代码初始化:
sock_fd is initialized by the following psuedocode:
int sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
fcntl(sock_fd, F_SETFL, flags | O_NONBLOCK);
bind(sock_fd, ...);
可能与此相关的是,此代码段在libevent循环内运行. libevent使用epoll()来确定UDP套接字是否很热.
Possibly related is that this code snippet is running inside a libevent loop. libevent is using epoll() to determine if the UDP socket is hot.
推荐答案
找到了我的答案. tl; dr-入站端不支持UDP.
Found my answer. tl;dr - UDP isn't supported on the inbound side.
经过足够的Google搜索,我偶然发现了论坛讨论和一些测试代码,其中打印出一张输入/输出fd类型及其支持的表格:
After enough Googling I stumbled upon a forum discussion and some test code which prints out a table of in/out fd types and their support:
$ ./a.out
in\out pipe reg chr unix tcp udp
pipe yes yes yes yes yes yes
reg yes no no no no no
chr yes no no no no no
unix no no no no no no
tcp yes no no no no no
udp no no no no no no
这篇关于Linux splice()返回EINVAL(“无效参数")的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!