ZBLOG

dma_alloc_contiguous在Linux驱动中使用的代码范例

在Linux内核中,dma_alloc_contiguous 是用于分配连续的DMA物理内存的一种接口。不过,实际使用中,我们通常会看到的是 dma_alloc_coherent 函数,它提供了更高层次的抽象,并适用于大多数场景。

以下是一个使用 dma_alloc_coherent 的示例代码,这个代码展示了如何在Linux设备驱动中分配和释放DMA缓冲区:

示例代码

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

struct my_device {
    void *virt_addr;       // 虚拟地址
    dma_addr_t phys_addr;  // 物理地址
    size_t size;           // 分配大小
};

static struct my_device *my_dev;

static int __init my_driver_init(void) {
    // 分配设备结构体
    my_dev = kmalloc(sizeof(struct my_device), GFP_KERNEL);
    if (!my_dev) {
        pr_err("Failed to allocate memory for device structure\n");
        return -ENOMEM;
    }

    // 设置要分配的DMA缓冲区大小(例如:1MB)
    my_dev->size = 1024 * 1024;

    // 分配连续DMA内存
    my_dev->virt_addr = dma_alloc_coherent(NULL, my_dev->size,
                                            &my_dev->phys_addr,
                                            GFP_KERNEL);
    
    if (!my_dev->virt_addr) {
        pr_err("Failed to allocate DMA coherent memory\n");
        kfree(my_dev);
        return -ENOMEM;
    }

    pr_info("Allocated %zu bytes of DMA memory at virtual address: %p, physical address: %pad\n",
            my_dev->size, my_dev->virt_addr, &my_dev->phys_addr);

    return 0;
}

static void __exit my_driver_exit(void) {
    if (my_dev && my_dev->virt_addr) {
        // 释放DMA内存
        dma_free_coherent(NULL, my_dev->size,
                          my_dev->virt_addr,
                          my_dev->phys_addr);
        
        pr_info("Freed DMA memory\n");
    }
    
    kfree(my_dev);
}

module_init(my_driver_init);
module_exit(my_driver_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("A simple example of using dma_alloc_coherent");
MODULE_AUTHOR("Your Name");

代码说明

  1. 头文件包含

    • 包含必要的头文件,如 module.hkernel.hdma-mapping.hslab.h
  2. 定义设备结构体

    • struct my_device 定义了一个简单的设备结构体,包含虚拟地址、物理地址和分配大小。
  3. 初始化函数 (my_driver_init)

    • 使用 kmalloc() 分配设备结构体。
    • 设置想要分配的DMA缓冲区大小(如1MB)。
    • 使用 dma_alloc_coherent() 函数申请连续的DMA内存,并获取其虚拟地址和物理地址。如果失败,则释放已分配资源并返回错误。
  4. 退出函数 (my_driver_exit)

    • 在模块卸载时,如果已经分配了DMA内存,则调用 dma_free_coherent() 释放它,并打印日志信息。
    • 最后释放设备结构体。
  5. 模块宏

    • 使用 module_init()module_exit() 来指定驱动程序加载和卸载时的函数。

注意事项

  • 确保在你的开发环境中,相关驱动框架正确安装,并且这个模块与目标硬件兼容。
  • 在实际情况中,你应该根据需要传入合适的参数来替代这里示例中的 NULL 指针(例如,与硬件相关的信息)。
  • 请遵循 Linux 内核编程的最佳实践,在不同上下文中使用这些API时注意可能发生的问题。


    内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://sdn.0voice.com/?id=6264

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?