2
dma_mmap_coherent()映射内存的零拷贝用户空间TCP发送
我正在Cyclone V SoC上运行Linux 5.1,这是一个FPGA,在一个芯片中具有两个ARMv7内核。我的目标是从外部接口收集大量数据,并通过TCP套接字流出(部分)这些数据。这里的挑战是数据速率非常高,并且可能接近饱和GbE接口。我有一个write()可行的实现,该实现只使用对套接字的调用,但其最高速度为55MB / s;大约是理论GbE限制的一半。我现在正在尝试使零拷贝TCP传输能够提高吞吐量,但是我遇到了麻烦。 为了将数据从FPGA传送到Linux用户空间,我编写了一个内核驱动程序。该驱动程序使用FPGA中的DMA块将大量数据从外部接口复制到连接到ARMv7内核的DDR3存储器中。当使用dma_alloc_coherent()with 进行探测时GFP_USER,驱动程序将该内存分配为一堆连续的1MB缓冲区,并通过mmap()在文件中实现并将这些/dev/地址返回给应用程序,将这些缓冲区公开给用户空间应用程序。dma_mmap_coherent()预分配的缓冲区。 到目前为止,一切都很好; 用户空间应用程序正在查看有效数据,吞吐率大于360MB / s时,还有足够的余量(外部接口的速度不够快,无法真正看到上限)。 为了实现零拷贝TCP网络,我的第一种方法是SO_ZEROCOPY在套接字上使用: sent_bytes = send(fd, buf, len, MSG_ZEROCOPY); if (sent_bytes < 0) { perror("send"); return -1; } 但是,这导致send: Bad address。 谷歌搜索了一段时间之后,我的第二种方法是使用管道,splice()然后执行以下操作vmsplice(): ssize_t sent_bytes; int pipes[2]; struct iovec iov = { .iov_base = buf, .iov_len = len }; pipe(pipes); sent_bytes …