Linux使用笔记
-- 随风看海
内存分配
-----------------------------------------------------------------------------------------------------------
kmalloc函数
--> 用于分配小块内存,物理连续
get_free_page相关函数
--> 可用于分配大块内存,物理连续
vmlloc函数
-->也用于分配内存,但其在虚拟地址连续,物理可能不连续
DMA
-----------------------------------------------------------------------------------------------------------
-----操作原理与方式-----
------------------------
DMA,是一种硬件机制,允许在不需要CPU参与的情况下,外围设备和主内存之间直接传输I/O数据。
读方式:
1. 主动获取(call read)
A. 应用进程通过read主动获取外设数据
B. CPU分配相应的DMA缓冲区,通知外设传送数据到该缓冲区,并将进程放进睡眠队列
C. 外设传送完毕后触发中断
D. CPU收到中断信号后,唤醒睡眠的进程,该进程现在可以从RAM里读取数据
2. 异步中断
A. 外设送中断信号给CPU, 表明有数据到来
B. CPU收到中断信号,通过中断处理函数分配相应的DMA缓冲区,并通知外设传送数据到该缓冲区
C. 外设传送数据到该缓冲区, 并在完成后发出另一个中断信号给CPU,告诉它完成了
D. CPU收到传送完成的中断信号后,唤醒相关的进程,并继续housekeeping
写方式:
1. 主动方式(write)
A. 应用进程通过write主动向外设发送数据
B. CPU分配相应的DMA缓冲区,将数据写往该缓冲区,并通知外设读取数据
C. 外设读取完毕后触发中断
D. CPU收到传送完毕中断信号后,告诉应用进程数据已发送
-----DMA缓冲区分配------
------------------------
注意点:
1. 当DMA的缓冲区大于一页时,它们必须占据连续的物理页面。
2. 由于有一些ISA设备的地址总线只有24位,不能寻下址到32位的内存,故对于这些设备,在分配DMA缓冲区时,要
使用GFP_DMA标志。
获得DMA缓冲区的常用方式:
1. 使用通用DMA层
对于DMA需要的大缓冲区,可以通过下面的两种方法分配:
1. 在系统引导时,通过向内核传递mem=val参数,保留顶部的RAM, 然后设备驱动可以通过ioremap来访问该预留的内存。
2. 如果设备支持的话,使用分散/聚集I/O (Scatter/gather I/O)
3. 使用GFP_NOFAIL标志分配缓冲区内存,非迫不得己,不建议使用
---------DMA映射--------
------------------------
1. DMA映射包括要分配的DMA缓冲区与为该缓冲区生成的、设备可访问地址的组合
2. DMA映射用dma_addr_t来表示总线地址,只允许将该地址变量传递给DMA支持的例程和设备本身,CPU直接使用它将不可预测
3. 两种DMA映射方式:
A. 一致性DMA映射 Coherent DMA mappings
存在于整个驱动生命周期中,必须保存在一致性缓存中, 且可以同时被CPU和外设访问,开销大,优化方法少,使用较少
dma_alloc_coherent --> 获得的最小大小可能为一页,对于小缓冲区,可能采用DMA池
dma_free_coherent
DMA池 -- 一个生成小型、一致性DMA映射的机制
dma_pool_create
dma_pool_destroy
dma_pool_alloc
dma_pool_free
B. 流式DMA映射 Streaming DMA mappings
通常为单独的操作建立,在给定时刻里只能被一个设备访问,开销小,优化能力强,建议使用
dma_map_single
dma_unmap_single
dma_map_page
dma_unmap_page
pci_dma_sync_single_for_cpu
pci_dma_sync_single_for_device
注意点:
B.1. 一旦缓冲区被映射,它将属于设备,而不是处理器,在缓冲区撤销映射前,驱动不能访问其中内容
B.2. 如果缓冲区位于设备不能访问的内存区段,有些系统可能会创建一个回弹缓冲区来给设备访问
阅读(1074) | 评论(0) | 转发(0) |