vmap函数接口用法及示例
vmap函数接口用法及示例
linux vmap函数接口用法及示例
Linux 内核中的 vmap
函数详解
vmap
是 Linux 内核中用于将一组物理上不连续的页面映射到连续虚拟地址空间的函数。它常用于需要大块”连续”虚拟内存但物理内存分散的场景(如 DMA 缓冲区、文件系统缓存等)。
函数原型
1 |
|
参数说明
参数 | 说明 |
---|---|
pages |
指向 struct page* 数组的指针,每个元素代表一个物理页 |
count |
要映射的物理页数量 |
flags |
映射行为标志: - VM_MAP :普通映射- VM_IOREMAP :I/O 内存映射 |
prot |
页面保护属性: - PAGE_KERNEL :内核读写权限- PAGE_KERNEL_RO :只读 |
返回值
- 成功:映射区域的起始虚拟地址(内核空间地址)
- 失败:
NULL
使用步骤
- 分配物理页:获取一组物理页(可离散)
- 构建 page 数组:创建
struct page*
数组并填充物理页指针 - **调用
vmap
**:映射到连续虚拟地址 - 使用虚拟地址:通过返回的虚拟地址访问内存
- 释放映射:使用
vunmap
解除映射
示例代码
1 |
|
关键说明
物理页来源:
- 示例使用
alloc_page()
分配零散物理页 - 实际场景可从其他来源获取(如
dma_alloc_coherent()
返回的物理页)
- 示例使用
内存释放:
- 必须调用
vunmap(vaddr)
解除映射 - 物理页需单独释放(示例中的
__free_page()
) - 数组内存需用
kfree(pages)
释放
- 必须调用
使用场景:
1
2
3
4
5
6// 典型场景:映射分散的物理页
struct page *dma_pages = get_dma_pages();
void *vaddr = vmap(dma_pages, count, VM_MAP, PAGE_KERNEL);
// 当作连续内存使用(如拷贝数据)
memcpy(vaddr, src_data, size);与
vmalloc
区别:特性 vmap
vmalloc
物理内存来源 由调用者提供(可离散) 自动分配零散物理页 虚拟地址连续性 连续 连续 适用场景 已有物理页需虚拟连续访问 直接分配大块虚拟连续内存
常见问题
为什么映射失败?
- 物理页不足(
alloc_page()
失败) - 虚拟地址空间耗尽(特别是 32 位系统)
- 无效的
flags
或prot
参数
- 物理页不足(
能否用于用户空间?
- 否!
vmap
返回的是内核空间地址,用户空间需通过mmap
等机制访问。
- 否!
性能注意事项:
- 频繁映射/解除映射会导致 TLB 刷新,影响性能
- 长期存在的映射更高效
提示:完整示例需编译为内核模块测试。确保系统有足够内存,并检查内核日志(
dmesg
)查看输出结果。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Helloeuler!