流式DMA映射演示:使用 dma_map_single

什么是DMA?

DMA(Direct Memory Access,直接内存访问)是一种允许硬件设备直接访问主内存的技术,而无需CPU的介入。这可以大大提高数据传输效率,减少CPU的负担。

为什么需要流式DMA映射?

在Linux内核中,DMA操作需要确保缓冲区的物理地址是连续的,并且缓存一致性得到正确处理。流式DMA映射是一种用于一次性DMA传输的映射方式,适用于数据流传输场景。

dma_map_single 函数

dma_map_single 是Linux内核中用于创建流式DMA映射的函数。它将一块内核缓冲区的虚拟地址映射为DMA可用的物理地址,并确保缓存一致性。

函数原型

dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size, enum dma_data_direction direction);

参数说明

参数 描述
dev 指向设备结构的指针
ptr 内核缓冲区的虚拟地址
size 映射区域的大小
direction 数据传输方向(DMA_TO_DEVICE, DMA_FROM_DEVICE, DMA_BIDIRECTIONAL)

示例代码

以下是一个简单的示例,演示如何使用 dma_map_single 函数映射一块内核缓冲区用于DMA传输:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>

static struct device *dev;
static void *buffer;
static dma_addr_t dma_handle;
static size_t buffer_size = 4096;

static int __init dma_example_init(void)
{
    int ret = 0;
    
    // 分配内核缓冲区
    buffer = kmalloc(buffer_size, GFP_KERNEL);
    if (!buffer) {
        pr_err("Failed to allocate buffer\n");
        return -ENOMEM;
    }
    
    // 获取设备结构(这里简化处理,实际应用中需要关联真实设备)
    dev = &some_device;
    
    // 映射缓冲区用于DMA传输(从设备到内存)
    dma_handle = dma_map_single(dev, buffer, buffer_size, DMA_FROM_DEVICE);
    if (dma_mapping_error(dev, dma_handle)) {
        pr_err("DMA mapping failed\n");
        kfree(buffer);
        return -ENOMEM;
    }
    
    pr_info("DMA mapping successful: virtual address %p, DMA address %pad\n",
            buffer, &dma_handle);
    
    return ret;
}

static void __exit dma_example_exit(void)
{
    // 取消DMA映射
    dma_unmap_single(dev, dma_handle, buffer_size, DMA_FROM_DEVICE);
    
    // 释放缓冲区
    kfree(buffer);
    
    pr_info("DMA example module unloaded\n");
}

module_init(dma_example_init);
module_exit(dma_example_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Streaming DMA Mapping Example");

DMA映射流程示意图

内核缓冲区 DMA设备 物理内存 dma_map_single() DMA传输

注意事项

常见问题

问题 解决方案
DMA映射失败 检查缓冲区大小和对齐,确保设备支持DMA
数据传输错误 验证数据传输方向是否正确,检查设备DMA配置
性能问题 考虑使用分散/聚集(scatter-gather)DMA以提高效率