Я пытаюсь поэкспериментировать с использованием вставки (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 инициализируется следующим псевдокодом:
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
инициализация выглядит ужасно. Проверьте возвращаемые значения! - person Karoly Horvath   schedule 17.08.2011