我在SoC上有一个FPGA,该FPGA可以连续生成和传输通过dma操作检索并放入RAM的大量数据。然后,它必须通过以太网端口以接近千兆位/秒的比特率发送到网络。 为了有效处理要传输的大量数据,我决定使用来自用户空间的sendfile系统调用。由于sendfile使用拼接机制,因此我的设备驱动程序支持拼接操作。
不幸的是,当输入文件描述符是我的驱动程序支持的字符设备文件时,sendfile返回-EINVAL。经过进一步调查,似乎Linux内核拒绝了常规或块以外的任何类型的文件。这就是Linux内核源代码所说的here:
/*
* 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作为输入。