У меня есть ПЛИС на SoC, которая непрерывно генерирует и передает огромное количество данных, которые извлекаются с помощью операций dma и помещаются в ОЗУ. Затем он должен быть отправлен в сеть через порт Ethernet с битрейтом, приближающимся к гигабит / с.
Чтобы эффективно обрабатывать большие объемы передаваемых данных, я решил использовать системный вызов sendfile из пространства пользователя. Поскольку sendfile использует механизм сращивания, мой драйвер устройства поддерживает операции сращивания.
К сожалению, sendfile возвращает -EINVAL, когда дескриптор входного файла - это файл моего символьного устройства, поддерживаемый моим драйвером. После дальнейшего исследования кажется, что ядро Linux отказывается от любого файла, отличного от обычного или блочного. Вот что говорит источник ядра Linux здесь :
/*
* We require the input being a regular file, as we don't want to
* randomly drop data for eg socket -> socket splicing. Use the
* piped splicing for that!
*/
i_mode = file_inode(in)->i_mode;
if (unlikely(!S_ISREG(i_mode) && !S_ISBLK(i_mode)))
return -EINVAL;
Справочная страница для sendfile (2), кажется, говорит то же самое:
Аргумент in_fd должен соответствовать файлу, который поддерживает mmap (2) -подобные операции (т. Е. Он не может быть сокетом).
Почему это? Я не очень хорошо понимаю техническую причину, которая запрещает этот случай, то есть использование sendfile в качестве дескриптора файла символьного устройства в качестве ввода.