Linux 驱动模型中的 Platform 机制
在 Linux 内核驱动开发中,平台设备(Platform Device)与平台驱动(Platform Driver)是硬件抽象与驱动解耦的核心机制,它通过统一的框架管理非标准总线(如嵌入式系统中的片上外设)的设备与驱动,解决了传统驱动模型中硬件依赖性强、可移植性差的问题,本文将深入剖析 Platform 机制的设计原理、核心组件及实践应用。

Platform 机制的设计背景
早期的 Linux 驱动开发常直接依赖硬件总线(如 PCI、I2C),但嵌入式系统中大量外设(如 UART、SPI 控制器、GPIO 控制器等)并非通过标准总线连接,而是直接集成在 SoC(System on Chip)上,这类设备缺乏总线抽象,导致驱动代码与硬件平台强耦合,难以跨平台复用。
为解决这一问题,Linux 内核引入了 Platform 机制,它将设备抽象为“平台设备”,将驱动抽象为“平台驱动”,通过内核的 platform 总线(platform_bus_type)实现设备与驱动的动态匹配,这种设计既保留了硬件的底层特性,又通过标准接口实现了驱动的模块化与可移植性。
核心组件解析
平台设备(Platform Device)
平台设备代表具体的硬件外设,其核心是 platform_device 结构体,包含设备名称、资源信息(如内存地址、中断号)及设备私有数据,设备注册通过 platform_device_register() 完成,内核会自动将其添加到 platform_bus_type 总线上。
资源描述是平台设备的关键,通过 platform_resource 结构体,设备可以声明其占用的硬件资源,
- 内存基址(
IORESOURCE_MEM) - 中断号(
IORESOURCE_IRQ) - DMA 通道(
IORESOURCE_DMA)
内核在设备注册时,会将这些资源信息记录在 /proc/iomem 和 /proc/interrupts 中,供驱动程序使用。
平台驱动(Platform Driver)
平台驱动负责实现设备的操作逻辑,其核心是 platform_driver 结构体,包含驱动的名称、设备匹配表(of_match_table 或 id_table)以及设备操作函数(probe、remove 等)。

驱动注册通过 platform_driver_register() 完成,内核会根据驱动的名称或设备匹配表,在总线上寻找对应的设备,匹配成功后,调用驱动的 probe 函数完成设备初始化;设备移除时,则调用 remove 函数进行资源清理。
设备与驱动的匹配机制
Platform 机制通过两种方式实现设备与驱动的匹配:
- 名称匹配:设备名(
platform_device.name)与驱动名(platform_driver.name)完全一致时触发匹配。 - 设备树(Device Tree)匹配:在 ARM 架构中,设备树(
.dts文件)通过compatible屏述设备兼容性,驱动的of_match_table定义兼容字符串列表,两者匹配成功即绑定。
关键数据结构与接口
platform_device 结构体
struct platform_device {
const char *name; // 设备名称,用于驱动匹配
int id; // 设备 ID,多设备实例时使用
struct device dev; // 内嵌的 device 结构体
u32 num_resources; // 资源数量
struct resource *resource; // 资源数组
const struct platform_device_id *id_entry; // 设备 ID 表
...
};
platform_driver 结构体
struct platform_driver {
int (*probe)(struct platform_device *); // 设备匹配成功时的回调
int (*remove)(struct platform_device *); // 设备移除时的回调
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver; // 内嵌的 device_driver 结构体
const struct platform_device_id *id_table; // 设备 ID 匹配表
const struct of_device_id *of_match_table; // 设备树匹配表
};
核心 API 接口
- 设备注册:
platform_device_register() - 驱动注册:
platform_driver_register() - 资源获取:
platform_get_resource()(获取内存/中断资源) - 硬件访问:
devm_ioremap_resource()(自动映射并释放内存资源)
实践应用流程
以一个简单的 LED 平台驱动为例,其开发流程如下:

定义平台设备
在板级文件(如 arch/arm/mach-xxx/board-xxx.c)中,定义 LED 设备的资源信息:
static struct resource led_resource[] = {
{
.start = 0x12340000, // LED 控制器物理地址
.end = 0x12340003,
.flags = IORESOURCE_MEM,
},
{
.start = 30, // 中断号
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device led_device = {
.name = "my_led", // 设备名称
.resource = led_resource,
.num_resources = ARRAY_SIZE(led_resource),
};
实现平台驱动
编写驱动代码(如 led.c),定义 platform_driver 并实现 probe 函数:
static int led_probe(struct platform_device *pdev) {
struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
void *virt_addr = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(virt_addr)) {
return PTR_ERR(virt_addr);
}
// 初始化 LED 硬件,注册字符设备等
return 0;
}
static const struct of_device_id led_of_match[] = {
{ .compatible = "vendor,led-ctrl" }, // 设备树兼容字符串
{ },
};
static struct platform_driver led_driver = {
.probe = led_probe,
.remove = led_remove,
.driver = {
.name = "my_led",
.of_match_table = led_of_match,
},
};
module_platform_driver(led_driver);
注册与匹配
设备与驱动分别通过 platform_device_register() 和 platform_driver_register() 注册到内核,当设备名“my_led”与驱动名匹配,或设备树 compatible 属性与驱动 of_match_table 匹配时,内核自动调用 led_probe 函数完成驱动加载。
优势与总结
Platform 机制通过以下优势简化了驱动开发:
- 硬件解耦:驱动代码通过标准接口访问硬件资源,无需关心具体平台细节。
- 资源管理自动化:
devm_系列函数(如devm_ioremap_resource)自动管理内存、中断等资源的分配与释放,避免内存泄漏。 - 可扩展性强:支持设备树动态配置,适应不同硬件平台的设备描述需求。
在嵌入式 Linux 开发中,Platform 机制已成为驱动开发的标准范式,它不仅提升了代码的可维护性和可移植性,还通过内核的统一管理降低了驱动开发的复杂度,为构建灵活、高效的嵌入式系统奠定了坚实基础。

















