蜗窝科技

DMA buffer及内存映射相关

蜗窝讨论区存档 · Linux kernel技术问答 · 楼主 wpeng_35097 · 2017-06-19 · 7 帖

本文是原「蜗窝讨论区」的历史存档(2017-06-19),来自版块「Linux kernel技术问答」,共 7 帖。讨论区已停止服务,此处仅供查阅。

wpeng_35097 · 2017-06-19 19:01

linuxer好, 最近在学习V4L2时产生一些疑问,麻烦@linuxer帮忙点拨以下理解是否正确? 1、在驱动实现的mmap接口函数中,可以使用dma_mmap_attrs把外部sensor申请的DMA缓冲区mmap到用户空间,此时之前申请DMA缓冲区的函数必须是dma_alloc_attrs,mmap之后相当于有两块虚拟地址对应了同一块物理地址。 2、dma_alloc_attrs和dma_alloc_coherent在用法上有什么区分吗?适用场景? 3、我看到像一些fb驱动实现的mmap调用的都是remap_pfn_range,网上说可以使用它来映射内存中的保留页、设备I/O、framebuffer、camera等内存。那是不是可以这样理解:remap_pfn_range作用是用来将物理地址映射到用户空间,ioremap作用是用来将物理地址映射到内核空间。 4、在videobuf2-dma-config.c中有dma-buf的实现,大概是一个供用户空间或其他设备驱动共享DMA buffer的技术,虽然使用步骤很简单(调用几个API)但我这里还是不太理解:假设1中的想法正确的话,那它和dma_mmap_attrs映射DMA缓冲区到用户空间的手段有什么区别吗,感觉dma_mmap_attrs也有“共享”的意思,ISP负责向DMA buffer放数据,用户空间负责从DMA buffer取数据。 5、ISP各个子模块间流通数据需要内存额外开辟buffer中转吗(比如preview、resizer、H3A之间),还是它们有相应的硬件缓冲区,只需要将最终处理完的数据放到内存buffer就OK了 6、像camera、framebuffer用的大内存都来自保留内存吗(mem=size),感觉这种方式比较粗放、浪费,有其它更好的技术吗?

以上问题麻烦@linuxer前辈解惑,等您不帮时回复即可,不胜感激!

linuxer · 2017-06-20 19:26

过两天再回复你

wpeng_35097 · 2017-06-20 19:47

感谢前辈关注,问题问的有些多还望@linuxer见谅,如果有些问题您觉得没什么价值,那就pass掉可以啦

linuxer · 2017-06-22 09:29

技术交流,不需要这么客气。

1、是的,两段虚拟地址mapping到了一个物理地址段。dma_alloc_attrs会返回一个虚拟地址,内核可以使用这个地址访问DMA buffer,dma_alloc_attrs同时会返回dma_handle这个bus address,用于外设访问DMA Buffer。dma_mmap_attrs会针对DMA buffer创建第二mapping,这次是mapping到userspace,方便进程用户空间直接访问DMA Buffer. 2、dma_alloc_coherent其实还有很多变种,例如dma_alloc_noncoherent, dma_alloc_writecombine等,因此为了统一起来,新内核提供了一个统一的dma_alloc_attrs函数来替代旧的dma_alloc_*系列函数接口。具体场景很复杂,和cpu arch、cpu和外设如何互联,cpu和memory如何互联相关,不是一句话可以讲清楚的,不过,对于普通驱动,使用dma_alloc_coherent分配coherent DMA buffer是最简单的,不需要考虑cpu和device在操作DMA Buffer上的同步。 3、你说的也对,但是这里可以补充一些信息。remap_pfn_range是把一个page frame(有对应的struct page与之对应,也就有pfn,page frame number)mapping到userspace的虚拟地址空间上去(vma)。ioremap一般不用于mapping page frame,它一般用来mapping外设的MMIO(寄存器地址空间)。 4、我对V4L2没有研究,不过我觉得videobuf2-dma-contig.c这个管理dma buffer的模块,最终应该还是通过dma_mmap_attrs把DMA buffer mapping到用户空间的,只不过它会附加一些管理dma buffer的功能。BTW,我猜的,仅供参考。 5、这个不是非常了解,不好回答。 6、想要大块的连续内存,可以在内核管理模块之外开辟reserved memory,这样驱动可以永远可以bring up,不会因为memory分配导致问题,不过,在不加载驱动的时候,那些保存的内存的确是有些浪费,也许CMA可以解决这个问题。

wpeng_35097 · 2017-06-24 22:16

多谢linuxer细心解答,这样就明白多了。 另外,“DMA controller做数据搬运期间,CPU可以并发地执行其他任务”像这样的描述一直不是很理解,DMA在占用总线传输数据时,CPU怎么还能并发执行呢?

linuxer · 2017-06-26 19:27

你这个问题其实和CPU系统架构相关的,如果整个系统的组件(cpu、dma controller、各种外设)都是在一条总线上的话,那么,当DAM发起bus transaction的时候,CPU已经不能发起第二个bus transaction,对memory进行访问了。不过现代的计算机系统的架构都不是那么的简单,各个cpu core有各自的cache或者共享的cache,DMA controller通过互连器件和cpu core进行互联,因此,各个cpu core以及DMA controller都是在不同的总线上,因此,虽然DMA占用了总线,并不影响cpu的并发。

温柔海洋 · 2017-07-01 12:04

感谢linuxer 百忙之中的回答。楼主 有空可以看看 kernel alsa 音频数据 也是通过dma 进行传输的。