Linux request_mem_region函数用法详解
Linux request_mem_region函数的用法及注意事项
request_mem_region
是 Linux 内核中用于申请 I/O 内存区域的函数,主要目的是标记一段物理地址空间为“已占用”,防止其他驱动或模块重复申请同一内存区域,从而避免资源冲突。以下是其用法和注意事项:
函数原型
1 |
|
- 参数:
start
:物理内存的起始地址。len
:需要申请的内存区域长度(字节数)。name
:设备或驱动的名称(用于标识资源所有者,可通过/proc/iomem
查看)。
- 返回值:
- 成功:返回非 NULL 的
struct resource
指针。 - 失败:返回
NULL
(表示该内存区域已被占用)。
- 成功:返回非 NULL 的
基本用法
在驱动初始化阶段申请内存区域:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
static struct resource *mem_region;
static int __init my_driver_init(void) {
mem_region = request_mem_region(MEM_START, MEM_LEN, "my_device");
if (!mem_region) {
printk(KERN_ERR "Failed to request memory region\n");
return -EBUSY; // 资源已被占用
}
// 后续操作:ioremap、访问硬件等
return 0;
}在驱动退出时释放内存区域:
1
2
3
4
5static void __exit my_driver_exit(void) {
if (mem_region) {
release_mem_region(MEM_START, MEM_LEN);
}
}
注意事项
必须检查返回值:
- 若
request_mem_region
返回NULL
,说明内存区域已被其他驱动占用,不可继续操作该区域,否则会导致系统不稳定或硬件冲突。
- 若
与
ioremap
配合使用:request_mem_region
仅标记内存区域为“已占用”,不映射物理地址到内核虚拟地址空间。实际访问硬件前,需通过ioremap
或ioremap_nocache
获取虚拟地址:1
void __iomem *virt_addr = ioremap(MEM_START, MEM_LEN);
释放资源必须成对调用:
- 使用
release_mem_region
释放内存区域,通常在模块退出函数中调用。若遗漏释放,可能导致资源泄漏,导致后续无法申请该区域。
- 使用
权限与并发访问:
- 确保在访问映射后的内存时使用正确的读写函数(如
readl
/writel
),避免直接使用指针操作。 - 若需在多个驱动间共享内存区域,需自行实现同步机制(如互斥锁)。
- 确保在访问映射后的内存时使用正确的读写函数(如
与
/proc/iomem
的关系:- 成功申请的内存区域会出现在
/proc/iomem
中,可通过此文件查看系统内存资源分配情况。
- 成功申请的内存区域会出现在
原子上下文限制:
request_mem_region
可能调用可能导致睡眠的函数(如kmalloc
),因此不能在原子上下文(如中断处理函数) 中调用。
现代内核的替代方案:
- 对于设备驱动,推荐使用资源管理 API(如
devm_request_mem_region
),它可自动释放资源,避免因驱动卸载时遗漏释放导致的问题:1
struct resource *mem_region = devm_request_mem_region(&pdev->dev, MEM_START, MEM_LEN, "my_device");
- 对于设备驱动,推荐使用资源管理 API(如
常见问题
- 资源冲突:若驱动无法申请到内存区域,需检查
/proc/iomem
确认是否被其他驱动占用。 - 地址对齐:确保
start
和len
符合硬件要求的对齐方式(如页对齐)。 - 平台依赖性:物理地址的取值范围与具体硬件平台相关(如 ARM、x86 差异)。
通过合理使用 request_mem_region
,可以确保驱动安全地管理硬件资源,避免系统级冲突。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Helloeuler!