这行代码是 Linux 内核中用于动态分配引脚描述符(pin descriptor)数组的典型实现,常见于 pinctrl 驱动的初始化阶段。以下是逐层解析:
1. 函数原型解析
pindesc = devm_kcalloc(&pdev->dev, info->ctrl->nr_pins, sizeof(*pindesc), GFP_KERNEL);
1.1 devm_kcalloc 函数
- 作用:内核设备管理(Device Managed)的内存分配函数,用于分配连续内存块,并自动绑定到设备生命周期。
- 特性:
- 内存会在设备驱动卸载时自动释放,无需手动调用
kfree。 - 分配的内存初始化为零(等效于
kcalloc)。
- 内存会在设备驱动卸载时自动释放,无需手动调用
- 参数:
&pdev->dev:指向当前设备的struct device指针,标记内存所属设备。info->ctrl->nr_pins:要分配的元素数量(即引脚总数)。sizeof(*pindesc):每个元素的大小(pindesc指向的结构体大小)。GFP_KERNEL:内存分配标志,表示在内核上下文中分配,可能触发睡眠。
2. 关键数据结构
2.1 pdev(Platform Device)
- 类型:
struct platform_device * - 含义:表示当前平台设备(如 SoC 上的 pinctrl 控制器)。
&pdev->dev:获取设备的struct device结构体,用于资源管理。
2.2 info(控制器信息)
- 类型:通常为
struct example_pinctrl *(驱动私有数据)。 info->ctrl:指向控制器描述符(如struct example_pinctrl_ctrl),包含:nr_pins:控制器管理的引脚总数。
2.3 pindesc(引脚描述符数组)
- 类型:
struct pin_desc *(假设pin_desc是引脚描述符结构体)。 - 含义:存储每个引脚的配置信息(如引脚号、功能、电气参数等)。
3. 代码逻辑
3.1 分配内存
- 目的:为控制器管理的所有引脚分配存储空间。
- 示例:若
nr_pins = 32,则分配32 * sizeof(struct pin_desc)字节的内存。 - 内存布局:
struct pin_desc { unsigned int pin; // 引脚编号(如 GPIO0) unsigned long function; // 功能复用配置(如 UART_TX) unsigned long config; // 电气参数(如上拉、驱动强度) // ... 其他字段 };
3.2 绑定到设备生命周期
- 通过
devm_kcalloc分配的内存会自动绑定到pdev->dev。 - 当设备驱动卸载时(如
remove函数被调用),内核会自动释放该内存,避免泄漏。
4. 典型使用场景
在 pinctrl 驱动的 probe 函数中,分配引脚描述符数组以初始化控制器:
static int example_pinctrl_probe(struct platform_device *pdev) {
struct example_pinctrl *info;
struct pin_desc *pindesc;
// 1. 分配驱动私有数据
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
// 2. 从设备树解析控制器信息(如引脚总数)
info->ctrl = parse_controller_dt(pdev);
// 3. 分配引脚描述符数组
pindesc = devm_kcalloc(&pdev->dev, info->ctrl->nr_pins,
sizeof(*pindesc), GFP_KERNEL);
// 4. 填充引脚描述符(如解析设备树中的引脚配置)
for (int i = 0; i < info->ctrl->nr_pins; i++) {
pindesc[i].pin = i;
pindesc[i].function = PIN_FUNCTION_GPIO;
}
// 5. 注册 pinctrl 设备
info->pctldev = pinctrl_register(&example_pinctrl_desc, &pdev->dev, info);
return 0;
}
5. 内存管理优势
- 自动释放:无需在
remove函数中手动释放pindesc。 - 避免泄漏:即使驱动初始化失败,内核也会清理已分配的内存。
- 简化代码:减少内存管理代码量,提升可维护性。
6. 替代方案对比
| 函数 | 行为 | 适用场景 |
|---|---|---|
devm_kcalloc | 分配并清零,自动释放 | 驱动初始化时分配长期使用的内存 |
kzalloc | 分配并清零,需手动释放 | 临时内存或非设备相关的内存 |
devm_kmalloc | 分配,自动释放 | 无需清零的内存(如结构体指针) |
总结
这行代码通过 devm_kcalloc 为 pinctrl 控制器分配了一个引脚描述符数组,实现了:
- 硬件抽象:为每个引脚存储配置信息,供后续引脚复用和电气参数配置使用。
- 资源安全:利用设备管理的内存分配,避免内存泄漏。
- 代码简洁:减少手动内存管理代码,聚焦核心逻辑(如寄存器操作)。
1093

被折叠的 条评论
为什么被折叠?



