Cache和DMA一致性
发布网友
发布时间:2024-10-23 15:55
我来回答
共1个回答
热心网友
时间:21小时前
Direct Memory Access (DMA) 技术允许硬件设备直接从内存中读取或写入数据,而无需 CPU 干预,从而提升系统性能。然而,DMA 和缓存之间存在着密切关系,特别是在数据不一致问题上。当 CPU 修改了部分数据仍保留在缓存中(采用写回机制)时,DMA 从内存获取数据可能获取到旧数据,导致程序运行异常。为了解决这一问题,缓存控制器需监视 DMA 的总线操作,以确保获取的数据来自缓存而非主存。不过,是否进行总线监视取决于硬件设计。总线监视技术允许缓存控制器监控内存访问,检查缓存命中情况,从而避免数据不一致。
为解决这一问题,操作系统容易采用支持物理地址查找的 PIPT 缓存实现总线监视技术。VIVT 缓存虽可根据虚拟地址查找,但不支持总线监视。VIPT 缓存在无别名情况下可以实现总线监视,但在存在别名时则不行。尽管总线监视技术透明地应用于软件,无需软件干涉,但并非所有硬件都支持此技术。在不支持总线监视的情况下,如何避免不一致问题成为关键。
为解决 DMA 相关问题,一种简便方法是在内存中为 DMA 操作申请一段没有缓存映射的缓冲区。将此缓冲区映射为 nocache 状态,可以避免缓存的影响。然而,此方法会导致性能损失,特别是当 DMA 操作不频繁或数据传输量较小时。在 Linux 系统中,dma_alloc_coherent() 接口采用此方法来分配 DMA 缓冲区。
为充分利用缓存带来的性能提升,可以采用缓存映射的 DMA 缓冲区。但需注意,根据 DMA 传输方向的不同,采取不同策略以维护缓存一致性。在 DMA 传输期间,CPU 不应访问 DMA 缓冲区,以避免缓存命中导致数据不一致。在 Linux 中,dma_map_single() 接口通过流式 DMA 实现了这一策略。
为了防止 DMA 缓冲区与其他数据共享缓存行,应确保 DMA 缓冲区首地址和大小均与缓存行对齐。如果 DMA 缓冲区不满足这一要求,可能导致数据不一致问题。在 Linux 中,分配 DMA 缓冲区时应避免使用栈和全局变量,以确保内存对齐。为此,使用 kmalloc 分配 DMA 缓冲区,并要求某些不支持总线监视的架构保证 kmalloc 分配的内存对齐。Linux 通过宏确保 kmalloc 分配的最小对象大小,从而满足对齐要求。