当前位置:  开发笔记 > 程序员 > 正文

Linux splice()返回EINVAL("无效参数")

如何解决《Linuxsplice()返回EINVAL("无效参数")》经验,为你挑选了2个好方法。

我正在尝试使用splice(man 2 splice)将数据从UDP套接字直接复制到文件.不幸的是,第一次调用splice()会返回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().目标文件在第一次调用splice时应该是无关紧要的,但为了完整性我将通过它打开它open(path, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR).两个调用都使用管道,除了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由以下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套接字是否很热.



1> bfallik-bamb..:

找到我的答案.tl; dr - 入站端不支持UDP.

经过足够的谷歌搜索,我偶然发现了一个论坛讨论和一些测试代码,打印出一个输入/输出fd类型的表格及其支持:

$ ./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



2> Nemo..:

是的,即使在最新的内核中,也绝不支持从UDP套接字读取.引用内核源代码如下.

splice调用do_splice在内核,它调用do_splice_to,该函数调用splice_read在成员file_operations结构的文件.

对于套接字,该结构在net/socket.c中定义为socket_file_ops,它将splice_read字段初始化为sock_splice_read.

反过来,该函数包含以下代码行:

if (unlikely(!sock->ops->splice_read))
    return -EINVAL;

ops套接字的字段是struct proto_ops.对于IPv4 UDP套接字,它初始化为inet_dgram_opsnet/ipv4/af_inet.c.最后,该结构没有明确地初始化该splice_read领域struct proto_ops; 即,它将其初始化为零.

所以sock_splice_read返回-EINVAL,然后传播.

推荐阅读
依然-狠幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有