4

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.

ただし、これらの条件はいずれも当てはまらないと思います。私はFedora15(カーネル2.6.40-4)を使用しているので、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は、次の擬似コードによって初期化されます。

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ソケットがホットかどうかを判別しています。

4

2 に答える 2

6

ええ、最新のカーネルであっても、UDP ソケットからの読み取りはサポートされていません。カーネル ソースへの参照は次のとおりです。

spliceファイルの構造体のメンバーを呼び出す を呼び出すdo_spliceカーネルで呼び出します。do_splice_tosplice_readfile_operations

ソケットの場合、その構造体はnet/socket.csplice_readで socket_file_ops として定義され、フィールドをに初期化しますsock_splice_read

その関数には、次のコード行が含まれています。

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

ソケットのopsフィールドはstruct proto_ops. IPv4 UDP ソケットの場合はinet_dgram_ops、 net/ipv4/af_inet.c で初期化されます。splice_read最後に、その構造体は のフィールドを明示的に初期化しませんstruct proto_ops。つまり、ゼロに初期化します。

そのため、 -EINVALsock_splice_readが返され、それが上に伝播します。

于 2011-08-17T04:59:09.027 に答える
6

私の答えを見つけました。tl;dr - UDP はインバウンド側ではサポートされていません。

十分なグーグル検索の後、フォーラムのディスカッションと、fd の in/out タイプとそれらのサポートの表を出力するいくつかのテスト コードに出くわしました。

$ ./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
于 2011-08-17T04:44:29.227 に答える