我試圖使用拼接(man 2 splice)將數據從UDP套接字直接複製到文件。不幸的是,第一次調用splice()會返回EINVAL。Linux 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()。目標文件在第一次拼接時應該是無關緊要的,但爲了完整起見,我通過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套接字是否很熱。
'sock_fd'初始化看起來很可怕。檢查返回值! –
這只是psuedocode。實際的代碼確實如此。我已經澄清了一點。 –