Linux内核设备驱动程序到内核空间的DMA

Linux内核设备驱动程序到内核空间的DMA,linux,linux-kernel,linux-device-driver,dma,Linux,Linux Kernel,Linux Device Driver,Dma,LDD3(p:453)使用作为参数传入的缓冲区演示dma\u map\u single bus_addr = dma_map_single(&dev->pci_dev->dev, buffer, count, dev->dma_dir); Q1:此缓冲区来自何处 kmalloc Q2:为什么DMA-API-HOWTO.txt声明我可以使用原始kmalloc进行DMA 形式 L:51如果您是通过页面分配器kmalloc()获取内存的,那么您可以使用这些例程返回的地址对该

LDD3(p:453)使用作为参数传入的缓冲区演示
dma\u map\u single

bus_addr = dma_map_single(&dev->pci_dev->dev, buffer, count, dev->dma_dir);
Q1:此缓冲区来自何处

kmalloc

Q2:为什么DMA-API-HOWTO.txt声明我可以使用原始
kmalloc
进行DMA

形式

L:51如果您是通过页面分配器kmalloc()获取内存的,那么您可以使用这些例程返回的地址对该内存进行DMA

L:74您不能接受kmap()调用的返回,也不能从中接收DMA

  • 所以我可以将从
    kmalloc
    返回的地址传递到我的硬件设备
  • 或者我应该先在它上面运行
    virt\u-to\u-bus
  • 或者我应该将其传递到
    dma\u map\u single
  • Q3:DMA传输完成后,我可以通过
    kmalloc
    地址读取内核驱动程序中的数据吗

    addr = kmalloc(...);
    ...
    printk("test result : 0x%08x\n", addr[0]);
    
    第四季度:将此信息传递到用户空间的最佳方式是什么

  • 复制到用户
  • mmap kmalloc内存
  • 其他人
  • kmalloc确实是获取缓冲区的一个来源。另一个可以是带有GFP_DMA标志的alloc_页面

  • 这意味着kmalloc返回的内存保证在物理内存中是连续的,而不仅仅是虚拟内存,因此您可以给出指向硬件的指针的总线地址。您确实需要在返回的地址上使用dma_map_single(),这取决于具体的平台,它可能不再是virt_to_总线的包装器,或者可能比do做得更多(设置IOMMU或GART表)

  • 正确,只需确保遵循DMA指南中解释的缓存一致性准则即可

  • 复制到用户将工作良好,是最简单的答案。根据您的具体情况,这可能足够了,或者您可能需要性能更好的产品。您不能正常地将K分配的地址映射到用户空间,但可以将DMA映射到用户提供的地址(某些注意事项适用)或分配用户页面(使用GFP用户的alloc_页面)


  • 祝你好运

    我将第二组编号为1和2的点的降价自动编号更改为3和4的编辑被拒绝(我想)是因为“dma_map_single”只是将虚拟地址转换为物理地址吗?