概述
在本章节中,我们将学习如何在Linux内核驱动中使用一致性DMA映射。通过dma_alloc_coherent
函数,我们可以分配一段DMA缓冲区,并将其内容导出到用户空间供查看。一致性DMA映射确保CPU和DMA设备可以看到一致的内存视图,无需软件缓存同步。
关键概念
- 一致性DMA映射: 保证CPU和DMA设备对内存的访问是一致的,无需显式缓存刷新。
- dma_alloc_coherent: 用于分配一致性DMA内存的函数。
- 用户空间接口: 通过设备文件(如
/dev/dma_buf
)将DMA缓冲区导出到用户空间。
函数和数据结构
函数/结构 | 描述 |
---|---|
dma_alloc_coherent |
分配一致性DMA内存,返回虚拟和物理地址。 |
dma_free_coherent |
释放由dma_alloc_coherent 分配的内存。 |
mmap |
将内核内存映射到用户空间。 |
struct file_operations |
定义设备文件操作的结构体。 |
代码示例
以下是一个简单的内核驱动示例,演示如何使用dma_alloc_coherent
分配DMA缓冲区,并通过mmap将其导出到用户空间。
驱动代码片段
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/dma-mapping.h>
#define DEVICE_NAME "dma_demo"
#define DMA_BUF_SIZE 4096
static void *dma_vaddr;
static dma_addr_t dma_paddr;
static struct device *dev;
static int dma_mmap(struct file *filp, struct vm_area_struct *vma)
{
return dma_mmap_coherent(dev, vma, dma_vaddr, dma_paddr, DMA_BUF_SIZE);
}
static struct file_operations fops = {
.mmap = dma_mmap,
};
static int __init dma_init(void)
{
dev = &pdev->dev; // 假设pdev是平台设备
dma_vaddr = dma_alloc_coherent(dev, DMA_BUF_SIZE, &dma_paddr, GFP_KERNEL);
if (!dma_vaddr) {
return -ENOMEM;
}
// 初始化DMA缓冲区内容
memset(dma_vaddr, 0xAB, DMA_BUF_SIZE);
// 注册设备等操作...
return 0;
}
static void __exit dma_exit(void)
{
dma_free_coherent(dev, DMA_BUF_SIZE, dma_vaddr, dma_paddr);
}
module_init(dma_init);
module_exit(dma_exit);
MODULE_LICENSE("GPL");
注意: 实际代码中需要处理错误检查、设备注册等细节。以上代码仅为演示核心概念。
用户空间访问
在用户空间,可以通过mmap系统调用将DMA缓冲区映射到进程的地址空间,然后直接访问其内容。
用户空间测试程序
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#define DMA_DEV "/dev/dma_demo"
#define BUF_SIZE 4096
int main()
{
int fd = open(DMA_DEV, O_RDWR);
if (fd < 0) {
perror("open");
return -1;
}
void *addr = mmap(NULL, BUF_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) {
perror("mmap");
close(fd);
return -1;
}
// 读取并打印DMA缓冲区的前16字节
printf("DMA Buffer content: ");
for (int i = 0; i < 16; i++) {
printf("%02X ", ((unsigned char *)addr)[i]);
}
printf("\n");
munmap(addr, BUF_SIZE);
close(fd);
return 0;
}
总结
通过本章的学习,我们掌握了如何使用dma_alloc_coherent
分配一致性DMA缓冲区,并通过mmap将其导出到用户空间。这种方法在需要高效DMA传输的应用中非常有用,如网络包处理、音频视频流处理等。
- 一致性DMA映射简化了内存管理,无需显式缓存同步。
dma_alloc_coherent
返回的物理地址可直接用于DMA设备。- 通过mmap将DMA缓冲区导出到用户空间,允许用户程序直接访问。