![O_DIRECT 访问 mmap-ed dmam_alloc_coherent() 问题](https://linux22.com/image/208911/O_DIRECT%20%E8%AE%BF%E9%97%AE%20mmap-ed%20dmam_alloc_coherent()%20%E9%97%AE%E9%A2%98.png)
我正在寻找克服这一障碍的想法。我有一个 Linux 内核模块,它从 Xilinx Zynq MPSOC 设备的 PL 端获取高速率数据。内核模块基于 dma-proxy 示例(https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/1027702787/Linux+DMA+From+User+Space+2.0)但我稍微修改了一下,只使用一个缓冲区。我们的 DMA 实现使用单通道、仅 Rx、非分散收集 IP 实现。我正在驱动程序中将数据移动到 dmam_alloc_coherent 内存空间。但是,当我映射到同一空间(如示例驱动程序中)时,我无法将此数据写入已使用 O_DIRECT 选项打开的用户空间文件。当我尝试这样做时, write() 调用错误并显示“错误地址”。不过,我可以在不使用 O_DIRECT 选项的情况下直接写入文件。然而,对于来自 PL 的传入数据来说,此数据速率太低。我尝试的下一件事是从 dmam_alloc_coherent() 内存区域到用户空间 posix_memalign(512) 分配区域进行第二次复制,然后依次将数据写入 O_DIRECT 打开的文件。这使得性能显着提高了约 5 倍。但它仍然没有达到应有的速度。
我的代码的场景性能摘要... (kernel)dmam_alloc_coherent() -> (userspace)file(O_DIRECT) =“错误地址” (kernel)dmam_alloc_coherent() -> (userspace)file() = 272 MB/秒(内核) )dmam_alloc_coherent() -> (用户空间)posix_memalign(512) -> (用户空间)文件(O_DIRECT) = 1323 MB/秒 (用户空间)posix_memalign(512) -> (用户空间)文件(O_DIRECT) = 2200 MB/秒(无实际的 PL 数据,只是将 memcontents 转储到磁盘)
我相信,如果我能找到一种方法让它工作,而不需要对 posix_memalign 区域执行第二次复制,我的速度应该接近 2000 MB/秒。我的实际目标速率是 1600 MB/秒。有谁知道我如何在没有第二个副本的情况下执行此操作?如何设置 dma 内存以允许在没有中间副本的情况下读取和写入 O_DIRECT 文件?哈哈,我相信这被称为零复制....
预先感谢您对此的所有帮助,我已经把头撞在墙上有一段时间了......
干杯!
附言。其他信息....
MPSOC 设置:MPSOC 开发板上的 Petalinux,具有在 ext4 LVM 条带设置中配置的 2 个 NVME 驱动器。
其他 dd 测试到磁盘:
1.dd if=/dev/zero of=tt/test.bin bs=20M count=50 50+0 条记录中的 50+0 条记录复制了 1048576000 字节(1.0 GB,1000 MiB),4.37955 秒,239 MB/s
2.dd if=/dev/zero of=tt/test.bin bs=20M count=50 oflag=direct 50+0条记录中的50+0条记录复制了1048576000字节(1.0 GB,1000 MiB),0.489777 s,2.1 GB/秒
3.dd if=/dev/zero of=tt/test.bin bs=30M count=1000 oflag=direct 1000+0条记录中的1000+0条记录复制了31457280000字节(31 GB,29 GiB),13.7039 s,2.3 GB/秒