Linux内核memremap设置为uncahche
Linux内核memremap设置为uncahche
Linux内核memremap设置为uncache
在Linux内核中,将内存映射设置为uncacheable
(不可缓存)通常用于访问设备寄存器或需要严格内存顺序的场景。以下是实现方法和关键步骤:
1. 使用 memremap
API
通过
memremap()
函数指定MEMREMAP_UC
标志实现不可缓存映射:1
2
3
void *addr = memremap(phys_addr, size, MEMREMAP_UC);- 参数说明:
phys_addr
: 要映射的物理地址起始位置size
: 映射区域的大小MEMREMAP_UC
: 映射为不可缓存(Uncacheable)
- 参数说明:
返回值:
- 成功:映射后的虚拟地址指针(
void __iomem *
类型) - 失败:
NULL
(需检查错误)
- 成功:映射后的虚拟地址指针(
解除映射:
1
memunmap(addr); // 使用后解除映射
2. 使用 ioremap
API(替代方案)
ioremap()
默认映射为不可缓存(等效于MEMREMAP_UC
):1
void *addr = ioremap(phys_addr, size);
- 解除映射使用
iounmap(addr)
- 解除映射使用
3. 关键注意事项
访问方式:
- 必须使用内核提供的I/O函数访问映射区域:其他函数:
1
2u32 val = readl(addr); // 读32位数据
writel(value, addr + offset); // 写32位数据readb()
/writeb()
(8位)、readw()
/writew()
(16位)。
- 必须使用内核提供的I/O函数访问映射区域:
缓存一致性:
- 不可缓存映射绕过CPU缓存,确保每次访问直接读写物理内存。
- 适用于设备寄存器(值可能随时变化)或DMA缓冲区(需避免缓存一致性问题)。
性能影响:
- 频繁访问时性能较低(无缓存加速),仅必要时使用。
地址对齐:
- 物理地址和大小通常需按页对齐(
PAGE_SIZE
,如4KB)。
- 物理地址和大小通常需按页对齐(
资源管理:
- 确保在模块退出或错误路径中调用
memunmap()
或iounmap()
释放资源。
- 确保在模块退出或错误路径中调用
4. 完整示例代码
1 |
|
5. 适用场景
- 设备寄存器访问(如硬件状态寄存器)
- DMA缓冲区(避免CPU缓存导致的脏数据问题)
- 特殊内存区域(如帧缓冲区、非一致性内存)
通过正确使用 MEMREMAP_UC
或 ioremap()
,可确保内核安全、高效地访问需要严格内存顺序的设备内存区域。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Helloeuler!