使用 dma_alloc_coherent
接口在 Linux 内核中分配 DMA 可用的内存是常见的操作,通常用于编写设备驱动程序。以下是一个简单的示例,展示了如何使用 dma_alloc_coherent
分配内存并在设备驱动中使用它。
示例:简单的字符设备驱动
这是一个基本的字符设备驱动,它在初始化时分配 DMA 共享内存,并在退出时释放它。
1. 驱动头文件和模块信息
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#define DEVICE_NAME "my_dma_device"
static int major_number;
static void *dma_buffer;
static dma_addr_t dma_handle;
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple DMA coherent memory example");
2. 打开和关闭函数
static int my_open(struct inode *inode, struct file *file) {
printk(KERN_INFO "Device opened\n");
return 0;
}
static int my_release(struct inode *inode, struct file *file) {
printk(KERN_INFO "Device closed\n");
return 0;
}
3. 文件操作结构体
static struct file_operations fops = {
.open = my_open,
.release = my_release,
};
4. 初始化和清理模块
static int __init my_init(void) {
// 注册字符设备
major_number = register_chrdev(0, DEVICE_NAME, &fops);
if (major_number < 0) {
printk(KERN_ALERT "Failed to register device: %d\n", major_number);
return major_number;
}
// 分配DMA一致性内存
dma_buffer = dma_alloc_coherent(NULL, PAGE_SIZE, &dma_handle, GFP_KERNEL);
if (!dma_buffer) {
unregister_chrdev(major_number, DEVICE_NAME);
printk(KERN_ALERT "Failed to allocate DMA buffer\n");
return -ENOMEM;
}
printk(KERN_INFO "DMA buffer allocated at %p with handle %pad\n", dma_buffer, &dma_handle);
return 0;
}
static void __exit my_exit(void) {
// 释放DMA一致性内存
if (dma_buffer)
dma_free_coherent(NULL, PAGE_SIZE, dma_buffer, dma_handle);
// 注销字符设备
unregister_chrdev(major_number, DEVICE_NAME);
printk(KERN_INFO "Device unregistered and DMA buffer freed\n");
}
5. 模块入口和出口函数
module_init(my_init);
module_exit(my_exit);
编译与加载模块
确保你的系统有适当的开发环境(如 kernel headers)。然后,可以创建一个 Makefile 来编译这个模块:
obj-m += my_dma_device.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
使用命令编译和加载模块:
make # 编译模块
sudo insmod my_dma_device.ko # 加载模块
dmesg # 查看内核日志以确认成功加载以及分配情况
sudo rmmod my_dma_device # 卸载模块
make clean # 清理生成文件
总结
上面的代码提供了一个简单的框架,用于在 Linux 驱动中使用 dma_alloc_coherent
。注意,这只是一个示例。在实际应用中,你需要根据具体硬件特性、错误处理等进行调整。
内容由零声教学AI助手提供,问题来源于学员提问