Linux kmap用法及示例详解
Linux kmap用法及示例
kmap
是 Linux 内核中用于将高端内存(High Memory)页面临时映射到内核虚拟地址空间的 API。它在 32 位系统(地址空间有限)中尤为重要,64 位系统中通常直接使用线性映射。
核心概念
- 高端内存(High Memory)
在 32 位 Linux 中,内核虚拟地址空间有限(通常 1GB)。当物理内存 > 896MB 时,超出部分称为高端内存,无法永久映射到内核空间,需动态映射。 kmap
作用
为高端内存页面分配一个临时内核虚拟地址,使内核能访问其内容。- 映射限制
映射槽位有限,需及时用kunmap
释放。
函数原型
1 |
|
使用步骤
- 获取目标页的
struct page*
(如通过alloc_page()
或页面缓存)。 - 调用
kmap(page)
获取内核虚拟地址。 - 通过返回的虚拟地址访问页面内容。
- 使用完成后调用
kunmap(page)
释放映射。
示例代码
示例 1:映射并修改页面内容
1 |
|
示例 2:从页面缓存读取文件内容
1 |
|
关键注意事项
- 映射生命周期
kmap
映射是临时的,用完后必须立即调用kunmap
。- 避免长期持有映射(可能导致槽位耗尽)。
- 原子上下文
kmap
可能睡眠(等待空闲槽位),不可在中断上下文或持有自旋锁时使用!此时需用kmap_atomic
(无睡眠,但映射仅限当前 CPU)。 - 64 位系统
64 位地址空间充足,kmap
通常直接返回page_to_virt(page)
(低开销),但为保持代码可移植性,仍需正确使用kmap/kunmap
。 - 错误处理
kmap
失败时返回NULL
(极罕见),需检查返回值。
kmap
vs kmap_atomic
特性 | kmap |
kmap_atomic |
---|---|---|
是否睡眠 | 可能睡眠(等待槽位) | 永不睡眠 |
适用上下文 | 进程上下文 | 进程/中断上下文 |
映射作用域 | 全局(跨 CPU) | 当前 CPU(迁移时失效) |
性能开销 | 较高 | 极低 |
解除映射函数 | kunmap(page) |
kunmap_atomic(addr) |
常见使用场景
- 文件系统操作(读写页面缓存)。
- 网络栈处理数据包(
skb_frag_t
页面)。 - 驱动程序访问用户空间页面(如
get_user_pages()
获取的页)。 - 内存管理子系统(如页交换、迁移)。
提示:现代内核中,许多操作已封装高层 API(如
kmap_local_page()
),但理解kmap
机制仍有助深入内核开发。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Helloeuler!