1. 功能概览
| 接口 | 作用对象 | 功能 | 虚拟地址属性 |
|---|---|---|---|
| ioremap() | 设备物理地址(MMIO) | 把 I/O 物理地址映射到内核虚拟地址 | 非缓存(UC,Uncached) |
| ioremap_wc() | 设备物理地址(显存、帧缓冲) | 把 I/O 物理地址映射到内核虚拟地址 | 写合并(WC,Write-Combining) |
| ioremap_cache() | 设备物理地址(支持 cache 的设备内存) | 把 I/O 物理地址映射到内核虚拟地址 | 可缓存(WB,Write-Back) |
| vmap() | 一组系统内存页 | 将离散的物理页映射到一块连续的虚拟地址 | 可缓存(WB) |
| kmap()/kmap_atomic() | 单个高端内存页 | 临时把一个物理页映射到低端内核虚拟地址供 CPU 访问 | 可缓存(WB) |
2. 主要区别
| 对比项 | ioremap / ioremap_wc / ioremap_cache | vmap | kmap |
|---|---|---|---|
| 输入对象 | 物理地址区间(通常来自设备 BAR、显存、MMIO) | struct page * 数组 |
单个 struct page * |
| 映射范围 | 可以映射大块连续物理地址 | 可以把离散页拼成连续虚拟区 | 一次只能映射一页 |
| 返回地址类型 | void __iomem *(需要 readl/writel 等 I/O 访问) |
普通内核指针,直接解引用 | 普通内核指针,直接解引用 |
| 缓存属性控制 | 可选择 UC/WC/WB | 固定 WB(系统内存) | 固定 WB(系统内存) |
| 典型用途 | 访问设备寄存器、显存、DMA 缓冲区 | 文件系统、驱动将分散页拼成连续虚拟区 | 内核访问高端内存页(ZONE_HIGHMEM) |
| 开销 | 分配 vmalloc 区域 + 建页表 + PAT/MTRR 设置 | 分配 vmalloc 区域 + 建页表 | 直接映射到固定 kmap 槽,开销小 |
| 能否用于设备地址 | ✅ 是(专用) | ❌ 否(只能映射系统 RAM) | ❌ 否(只能映射系统 RAM) |
3. 典型使用场景示例
ioremap()
用于访问设备寄存器(PCI BAR),避免 CPU cache 导致寄存器读写出错。
void __iomem *regs = ioremap(pci_resource_start(pdev, 0), len);
val = readl(regs + OFFSET);
writel(val, regs + OFFSET);
ioremap_wc()
用于映射显存帧缓冲,提高写入吞吐量。
void __iomem *fb = ioremap_wc(fb_phys_addr, fb_size);
memset_io(fb, 0xff, fb_size); // 用写合并提升性能
ioremap_cache()
用于支持 cache 的设备 RAM,比如一些共享内存设备。
void __iomem *buf = ioremap_cache(dev_phys_mem, size);
memcpy_toio(buf, src, size);
vmap()
将分散的 page 映射成一块连续虚拟地址供内核访问。
struct page *pages[n];
void *vaddr = vmap(pages, n, VM_MAP, PAGE_KERNEL);
memset(vaddr, 0, n * PAGE_SIZE);
kmap() / kmap_atomic()
用于临时访问高端内存页。
void *vaddr = kmap(page);
do_something(vaddr);
kunmap(page);
- 直观示意图
物理地址空间:
+-----------+-----------------+-------------+
| 系统 RAM | 设备寄存器/MMIO | 显存/外设RAM|
+-----------+-----------------+-------------+
内核虚拟地址空间:
+-----------+--------------------------------+-------------------+
| 直接映射 | vmalloc/ioremap 区 (ioremap/vmap)| kmap 区 (高端页映射)|
+-----------+--------------------------------+-------------------+
^ ^ ^
| | |
普通RAM映射 ioremap/vmap映射 kmap单页临时映射
- 记忆口诀
ioremap*:映射设备物理地址,能控制缓存属性,返回 __iomem 指针。
vmap:映射已有的普通物理页,拼成连续虚拟区。
kmap:映射单个物理页,主要给高端内存用。
JINHU