Linux内核设备驱动程序DMA进入内核空间

LDD3(p:453)使用传入的缓冲区作为参数演示dma_map_single

 bus_addr = dma_map_single(&dev->pci_dev->dev, buffer, count, dev->dma_dir); 

Q1 :这个缓冲区是从哪里来的?

kmalloc

Q2 :为什么DMA-API-HOWTO.txt状态我可以使用原始的kmalloc来DMA?

表格http://www.mjmwired.net/kernel/Documentation/DMA-API-HOWTO.txt

L:51如果通过页面分配器kmalloc()获取了内存,那么可以使用从这些例程返回的地址来从内存中获取内存。

L:74你不能把kmap()调用和DMA返回给它。

  1. 所以我可以将从kmalloc返回的地址传递给我的硬件设备?
  2. 还是应该先运行virt_to_bus
  3. 或者我应该通过这个dma_map_single

问题3 :当DMA传输完成后,我可以通过kmalloc地址读取内核驱动程序中的数据吗?

 addr = kmalloc(...); ... printk("test result : 0x%08x\n", addr[0]); 

Q4 :什么是最好的方式来获得这个用户空间?

  1. copy_to_user
  2. mmap的kmalloc内存?
  3. 其他?

Solutions Collecting From Web of "Linux内核设备驱动程序DMA进入内核空间"

  1. kmalloc确实是获得缓冲区的一个来源。 另一个可以是GFP_DMA标志的alloc_page。

  2. 其含义是保证kmalloc返回的内存在物理内存中是连续的,而不仅仅是虚拟内存,所以你可以把这个指针的总线地址给你的硬件。 你确实需要在返回的地址上使用dma_map_single(),这取决于确切的平台可能不会再包装virt_to_bus或者可能做更多的事情(建立IOMMU或GART表)

  3. 正确的,只要确保遵循高速缓存一致性准则,如DMA指南解释。

  4. copy_to_user将正常工作,是最简单的答案。 根据您的具体情况,可能已经足够了,或者您可能需要更好的性能。 你不能正常地将kmalloced地址映射到用户空间,但是你可以DMA进入用户提供的地址(应用一些注意事项)或者分配用户页面(alloc_page用GFP_USER)

祝你好运!