Я пытаюсь поэкспериментировать с использованием соединения ( man 2 splice ) для копирования данных из UDP-сокета прямо в файл.К сожалению, при первом вызове splice () возвращается EINVAL.
Страница man заявляет:
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 инициализируется следующим псевдокодом:
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.