dma_alloc_contiguous
是一个用于在 Linux 内核中分配连续 DMA 物理内存的接口。它主要用于设备驱动程序,以确保为设备分配的内存是物理上连续的,从而满足某些硬件对内存地址的要求。
下面是 dma_alloc_contiguous
的使用示例,适用于 Linux 驱动开发。
示例代码
#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");
代码说明
包含必要的头文件:包括了所需的库,例如
module.h
和dma-mapping.h
。定义设备结构体:包含虚拟地址、物理地址和分配大小等信息。
初始化函数 (
my_driver_init
):- 首先分配设备结构体。
- 然后设置要分配的DMA缓冲区大小。
- 使用
dma_alloc_coherent()
函数申请连续的DMA内存,并获取其虚拟地址和物理地址。如果失败,则清理并返回错误。
退出函数 (
my_driver_exit
):- 在模块卸载时,释放已分配的DMA内存和设备结构体。
模块宏:使用
module_init()
和module_exit()
宏来指定模块的入口和出口点。
注意事项
- 确保在你的系统上编译这个模块时,相关驱动框架已经正确安装。
- 上述代码中的
NULL
参数传递给dma_alloc_coherent()
表示没有特定于设备上下文。在实际情况中,应该传入与硬件相关的信息,例如相应的设备结构指针。 - 请根据具体需求调整缓冲区大小和其它参数。这只是一个基本示例,用于展示如何调用这个接口。
内容由零声教学AI助手提供,问题来源于学员提问