在Linux内核中,总线、设备和驱动三者构成了设备模型的核心,它们之间依靠匹配机制协同工作,实现了硬件资源的动态发现、管理和驱动加载。下面简单梳理它们的关系。

总线

  • bus_type 定义:include/linux/device.h
struct bus_type {
	const char		*name;
	const char		*dev_name;
	struct device		*dev_root;
	struct device_attribute	*dev_attrs;	/* use dev_groups instead */
	const struct attribute_group **bus_groups;
	const struct attribute_group **dev_groups;
	const struct attribute_group **drv_groups;

	int (*match)(struct device *dev, struct device_driver *drv);
	int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
	int (*probe)(struct device *dev);
	int (*remove)(struct device *dev);
	void (*shutdown)(struct device *dev);

	int (*online)(struct device *dev);
	int (*offline)(struct device *dev);

	int (*suspend)(struct device *dev, pm_message_t state);
	int (*resume)(struct device *dev);

	const struct dev_pm_ops *pm;

	const struct iommu_ops *iommu_ops;

	struct subsys_private *p;
	struct lock_class_key lock_key;
};

以下是针对 struct bus_type(总线类型结构体)的详细说明。该结构体在 Linux 设备模型中扮演核心角色,用于表示系统中的一个总线,如 PCI、USB、I2C 等。总线是处理器与其下挂载设备之间的通道,即使某些总线是内部的或虚拟的(如平台总线),也由其统一管理。

结构体字段详细说明

  1. name
    类型:const char *
    作用:总线的名称,如 “pci”、”usb”、”i2c” 等。这是总线的唯一标识,用于在系统中注册和识别总线类型。
  2. dev_name
    类型:const char *
    作用:用于子系统为设备生成名称的格式化字符串模板(如 “foo%u”,其中 %u 会被设备 ID 替换),便于在 /sys/bus/ 下统一命名设备节点。
  3. dev_root
    类型:struct device *
    作用:指向该总线的默认父设备。在设备注册时,若无显式指定父设备,则使用此设备作为父节点(通常在 sysfs 中体现为设备的上级目录)。
  4. dev_attrs(已弃用)
    类型:struct device_attribute *
    作用:总线上设备的默认属性数组(旧版接口),现推荐使用 dev_groups 替代。属性用于在 sysfs 中暴露设备信息(如设备号、状态等)。
  5. bus_groups
    类型:const struct attribute_group **
    作用:总线本身的属性组,用于在 sysfs 的总线目录(如 /sys/bus/pci/)下创建属性文件,例如总线的版本号、支持的功能等。
  6. dev_groups
    类型:const struct attribute_group **
    作用:总线上所有设备的默认属性组。当设备注册到该总线时,这些属性会自动添加到设备的 sysfs 目录中,无需每个设备驱动单独定义。
  7. drv_groups
    类型:const struct attribute_group **
    作用:总线上设备驱动的默认属性组。这些属性会添加到每个注册到该总线的驱动的 sysfs 目录中,用于展示或配置驱动相关参数。

关键方法(回调函数):

  1. match
    函数签名:int (*match)(struct device *dev, struct device_driver *drv)
    作用:当新设备或驱动添加到总线时调用,判断设备是否可由指定驱动处理。返回非零值表示匹配成功,触发后续的 probe 操作。
  2. uevent
    函数签名:int (*uevent)(struct device *dev, struct kobj_uevent_env *env)
    作用:在设备添加、移除或状态变更时调用,用于向用户空间发送 uevent 事件(如 udev 规则触发),并可添加自定义环境变量。
  3. probe
    函数签名:int (*probe)(struct device *dev)
    作用:当设备与驱动匹配成功后调用,负责初始化设备。通常会调用具体设备驱动的 probe 函数完成硬件检测和资源配置。
  4. remove
    函数签名:int (*remove)(struct device *dev)
    作用:当设备从总线移除时调用,用于清理资源、注销设备,防止内存泄漏或资源冲突。
  5. shutdown
    函数签名:void (*shutdown)(struct device *dev)
    作用:在系统关机时调用,确保设备安全进入静默状态,停止所有操作。

电源管理相关方法:

  1. online / offline
    函数签名:int (*online)(struct device *dev) / int (*offline)(struct device *dev)
    作用:用于设备的热插拔管理。online 将设备重新上线(如恢复电源),offline 则使设备离线(如准备热移除),执行失败会阻止操作。
  2. suspend / resume
    函数签名:int (*suspend)(struct device *dev, pm_message_t state) / int (*resume)(struct device *dev)
    作用:设备睡眠/唤醒回调。suspend 将设备置为低功耗状态,resume 恢复其正常运行。state 参数指定睡眠的深度(如待机、休眠)。
  3. pm
    类型:const struct dev_pm_ops *
    作用:指向电源管理操作集的结构体,包含更细粒度的 PM 回调(如 runtime_suspend、runtime_resume),委托给具体设备驱动的 PM 实现。

其他字段:

  1. iommu_ops
    类型:const struct iommu_ops *
    作用:IOMMU(输入输出内存管理单元)相关操作,用于总线级别的地址翻译和设备隔离,常用于虚拟化或安全场景。
  2. p
    类型:struct subsys_private *
    作用:驱动核心私有数据,仅由内核设备模型内部使用,包含设备链表、驱动链表、互斥锁等,对外不可见。
  3. lock_key
    类型:struct lock_class_key
    作用:锁验证器(lockdep)使用的锁分类键,用于调试内核中的锁依赖关系,防止死锁。

struct bus_type 是 Linux 设备模型的核心组件,通过统一的接口管理总线行为,包括设备枚举、驱动匹配、电源管理、sysfs 属性展示等。它使不同总线(如物理的 PCI 或虚拟的平台总线)能够以一致的方式集成到内核中,支持动态设备发现和热插拔。

驱动

  • device_driver定义:include/linux/device.h
struct device_driver {
	const char		*name;
	struct bus_type		*bus;

	struct module		*owner;
	const char		*mod_name;	/* used for built-in modules */

	bool suppress_bind_attrs;	/* disables bind/unbind via sysfs */
	enum probe_type probe_type;

	const struct of_device_id	*of_match_table;
	const struct acpi_device_id	*acpi_match_table;

	int (*probe) (struct device *dev);
	int (*remove) (struct device *dev);
	void (*shutdown) (struct device *dev);
	int (*suspend) (struct device *dev, pm_message_t state);
	int (*resume) (struct device *dev);
	const struct attribute_group **groups;

	const struct dev_pm_ops *pm;

	struct driver_private *p;
};

以下是针对 struct device_driver(设备驱动结构体)的详细说明。该结构体在 Linux 设备模型中用于表示一个设备驱动程序,负责管理特定类型的设备,并与总线协同工作来实现设备的初始化、操作和电源管理。

结构体字段详细说明

  1. name
    类型:const char *
    作用:驱动的名称,在系统中唯一标识该驱动。通常与驱动模块的名称一致(如 “e1000” 用于 Intel 网卡驱动)。在 /sys/bus/xxx/drivers/ 目录下会以其命名。
  2. bus
    类型:struct bus_type *
    作用:指向该驱动所属的总线类型(如 &pci_bus_type)。驱动必须注册到对应的总线,以便总线核心在设备枚举时调用驱动的 probe 函数。
  3. owner
    类型:struct module *
    作用:指向拥有该驱动的模块(通常使用 THIS_MODULE)。用于模块引用计数管理,防止驱动模块在设备仍在使用时被卸载。
  4. mod_name
    类型:const char *
    作用:内置模块(built-in)的名称。对于编译进内核的驱动,此字段指定模块名,用于调试或日志记录。
  5. suppress_bind_attrs
    类型:bool
    作用:若为 true,则禁止通过 sysfs 进行驱动的绑定(bind)和解绑(unbind)操作。常用于核心驱动,避免用户空间意外导致设备失效。
  6. probe_type
    类型:enum probe_type
    作用:指定驱动的探测类型,影响设备与驱动的匹配时机。可选值包括:
    PROBE_FORCE_SYNCHRONOUS:强制同步探测。
    PROBE_DEFAULT_STRATEGY:默认异步探测等。
  7. of_match_table
    类型:const struct of_device_id *
    作用:设备树(Device Tree)匹配表,用于描述驱动支持的设备树兼容性字符串(如 { .compatible = “vendor,device” })。在嵌入式系统中,设备树节点通过此表与驱动匹配。
  8. acpi_match_table
    类型:const struct acpi_device_id *
    作用:ACPI(高级配置与电源接口)设备匹配表,用于 ACPI 系统中的设备标识匹配。

关键操作回调函数:

  1. probe
    函数签名:int (*probe)(struct device *dev)
    作用:当设备与驱动通过总线匹配成功后调用。驱动在此函数中初始化设备、分配资源、注册中断等。返回 0 表示成功,负数表示错误。
  2. remove
    函数签名:int (*remove)(struct device *dev)
    作用:当设备断开或驱动卸载时调用,用于释放资源、注销中断、清理设备状态。
  3. shutdown
    函数签名:void (*shutdown)(struct device *dev)
    作用:系统关机时调用,确保设备安全停止操作(如关闭电源、保存状态)。
  4. suspend / resume
    函数签名:int (*suspend)(struct device *dev, pm_message_t state) / int (*resume)(struct device *dev)
    作用:设备电源管理回调。suspend 将设备置为低功耗状态,resume 恢复设备运行。state 参数指定休眠深度(如 PM_SUSPEND_TO_RAM)。

其他字段:

  1. groups
    类型:const struct attribute_group **
    作用:驱动的默认属性组,用于在 sysfs 的驱动目录(如 /sys/bus/pci/drivers/e1000/)下自动创建属性文件,暴露驱动信息或配置选项。
  2. pm
    类型:const struct dev_pm_ops *
    作用:指向电源管理操作集的指针,包含更细粒度的电源管理回调(如 runtime_suspend、runtime_resume),用于设备运行时电源控制。
  3. p
    类型:struct driver_private *
    作用:驱动核心的私有数据,由设备模型内部使用,包含驱动状态、设备链表、锁等,对外部透明。

struct device_driver 是 Linux 设备驱动框架的核心结构体,它定义了驱动与总线、设备的交互接口。通过实现其回调函数(如 probe、remove),驱动能够响应设备的生命周期事件。结合设备树或 ACPI 的匹配机制,它支持动态设备发现和自动加载,是实现硬件抽象和跨平台兼容性的关键。

设备

  • device定义:include/linux/device.h
struct device {
	struct device		*parent;

	struct device_private	*p;

	struct kobject kobj;
	const char		*init_name; /* initial name of the device */
	const struct device_type *type;

	struct mutex		mutex;	/* mutex to synchronize calls to
					 * its driver.
					 */

	struct bus_type	*bus;		/* type of bus device is on */
	struct device_driver *driver;	/* which driver has allocated this
					   device */
	void		*platform_data;	/* Platform specific data, device
					   core doesn't touch it */
	void		*driver_data;	/* Driver data, set and get with
					   dev_set/get_drvdata */
	struct dev_pm_info	power;
	struct dev_pm_domain	*pm_domain;

#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
	struct irq_domain	*msi_domain;
#endif
#ifdef CONFIG_PINCTRL
	struct dev_pin_info	*pins;
#endif
#ifdef CONFIG_GENERIC_MSI_IRQ
	struct list_head	msi_list;
#endif

#ifdef CONFIG_NUMA
	int		numa_node;	/* NUMA node this device is close to */
#endif
	u64		*dma_mask;	/* dma mask (if dma'able device) */
	u64		coherent_dma_mask;/* Like dma_mask, but for
					     alloc_coherent mappings as
					     not all hardware supports
					     64 bit addresses for consistent
					     allocations such descriptors. */
	unsigned long	dma_pfn_offset;

	struct device_dma_parameters *dma_parms;

	struct list_head	dma_pools;	/* dma pools (if dma'ble) */

	struct dma_coherent_mem	*dma_mem; /* internal for coherent mem
					     override */
#ifdef CONFIG_DMA_CMA
	struct cma *cma_area;		/* contiguous memory area for dma
					   allocations */
#endif
	/* arch specific additions */
	struct dev_archdata	archdata;

	struct device_node	*of_node; /* associated device tree node */
	struct fwnode_handle	*fwnode; /* firmware device node */

	dev_t			devt;	/* dev_t, creates the sysfs "dev" */
	u32			id;	/* device instance */

	spinlock_t		devres_lock;
	struct list_head	devres_head;

	struct klist_node	knode_class;
	struct class		*class;
	const struct attribute_group **groups;	/* optional groups */

	void	(*release)(struct device *dev);
	struct iommu_group	*iommu_group;

	bool			offline_disabled:1;
	bool			offline:1;
};

以下是 struct device(设备结构体)的详细说明。该结构体是Linux设备模型中最核心的数据结构之一,用于表示系统中的每个物理或逻辑设备,并管理设备的生命周期、资源、电源管理、与总线和驱动的关联等。

结构体字段详细说明

  1. parent
    类型:struct device *
    作用:指向父设备的指针,用于构建设备层次结构。在sysfs中表现为目录嵌套关系(如USB设备以USB控制器为父设备)。
  2. p
    类型:struct device_private *
    作用:设备核心的私有数据,仅由设备模型内部使用,包含设备状态、链表、锁等管理信息。
  3. kobj
    类型:struct kobject
    作用:内嵌的kobject核心对象,负责设备的sysfs表示、引用计数管理和热插拔事件(uevent)基础。
  4. init_name
    类型:const char *
    作用:设备的初始名称。如果未设置,内核在注册时会根据总线或设备ID自动生成名称。
  5. type
    类型:const struct device_type *
    作用:指向设备类型的指针,定义特定类型设备的通用属性和操作(如网络设备、块设备等特有行为)。
  6. mutex
    类型:struct mutex
    作用:互斥锁,用于同步对设备的操作(如probe、remove),防止并发访问导致竞态条件。
  7. bus
    类型:struct bus_type *
    作用:设备所属的总线类型(如&pci_bus_type)。总线核心通过此字段管理设备的匹配与探测流程。
  8. driver
    类型:struct device_driver *
    作用:指向当前绑定到该设备的驱动。在总线匹配成功后由设备模型设置,用于驱动与设备的关联。
  9. platform_data
    类型:void *
    作用:平台相关的私有数据,由板级代码或固件传递,驱动可读取但设备核心不修改(如硬件配置参数)。
  10. driver_data
    类型:void *
    作用:驱动的私有数据,通过dev_set_drvdata()/dev_get_drvdata()访问,用于存储驱动实例的上下文信息。
  11. power
    类型:struct dev_pm_info
    作用:设备的电源管理状态信息,包括当前电源状态、唤醒能力等。
  12. pm_domain
    类型:struct dev_pm_domain *
    作用:指向电源管理域的指针,用于对一组设备进行统一的电源状态控制(如SoC子系统的电源管理)。
  13. msi_domain(条件编译)
    类型:struct irq_domain *
    作用:MSI(消息信号中断)中断域,用于管理设备的高级中断功能(需开启CONFIG_GENERIC_MSI_IRQ_DOMAIN)。
  14. pins(条件编译)
    类型:struct dev_pin_info *
    作用:设备引脚控制信息,用于管理引脚复用、配置状态(需开启CONFIG_PINCTRL)。
  15. msi_list(条件编译)
    类型:struct list_head
    作用:MSI中断描述符链表,维护设备使用的MSI中断列表(需开启CONFIG_GENERIC_MSI_IRQ)。
  16. numa_node(条件编译)
    类型:int
    作用:设备所在的NUMA节点编号,用于优化内存分配(使内存接近设备,需开启CONFIG_NUMA)。
  17. dma_mask
    类型:u64 *
    作用:DMA地址掩码,限制设备DMA可访问的内存地址范围(如32位设备设置为0xFFFFFFFF)。
  18. coherent_dma_mask
    类型:u64
    作用:一致性DMA掩码,用于分配设备与CPU共享缓存的一致性内存映射。
  19. dma_pfn_offset
    类型:unsigned long
    作用:物理地址与DMA地址的页框号偏移,用于处理IOMMU或特殊内存布局的平台。
  20. dma_parms
    类型:struct device_dma_parameters *
    作用:DMA参数配置,包括最大段大小、段数量等,用于优化DMA映射操作。
  21. dma_pools
    类型:struct list_head
    作用:DMA内存池链表,用于管理小对象DMA内存的分配与释放。
  22. dma_mem
    类型:struct dma_coherent_mem *
    作用:指向设备的一致性DMA内存区域,用于覆盖默认的DMA分配器。
  23. cma_area(条件编译)
    类型:struct cma *
    作用:连续内存分配器(CMA)区域,用于DMA内存的预留管理(需开启CONFIG_DMA_CMA)。
  24. archdata
    类型:struct dev_archdata
    作用:架构相关的私有数据,由各CPU平台自行定义和使用。
  25. of_node
    类型:struct device_node *
    作用:指向设备树(Device Tree)中对应节点的指针,用于从设备树获取配置信息(如寄存器地址、中断号)。
  26. fwnode
    类型:struct fwnode_handle *
    作用:通用固件节点句柄,支持设备树、ACPI等多种固件接口。
  27. devt
    类型:dev_t
    作用:设备号,用于在/dev目录下创建设备文件节点。
  28. id
    类型:u32
    作用:设备实例ID,用于区分同类型的多个设备(如多个网卡序号)。
  29. devres_lock
    类型:spinlock_t
    作用:设备资源(devres)管理的自旋锁,保护资源链表的并发访问。
  30. devres_head
    类型:struct list_head
    作用:设备资源链表头,用于自动管理驱动分配的资源(避免资源泄漏)。
  31. knode_class
    类型:struct klist_node
    作用:链表节点,用于将设备链接到所属的设备类(如class)中。
  32. class
    类型:struct class *
    作用:设备所属的类别(如”input”、”block”),用于在/sys/class/下分类管理设备。
  33. groups
    类型:const struct attribute_group **
    作用:设备的默认属性组,在sysfs中自动创建属性文件(如设备信息、状态等)。
  34. release
    类型:void (*release)(struct device *dev)
    作用:设备引用计数归零时调用的回调函数,负责释放设备占用的资源。每个设备必须实现此函数。
  35. iommu_group
    类型:struct iommu_group *
    作用:IOMMU组指针,用于管理共享IOMMU域的设备(如PCIe设备透传)。
  36. offline_disabled
    类型:bool
    作用:如果为true,则禁止设备离线(如关键设备不允许热插拔)。
  37. offline
    类型:bool
    作用:标识设备当前是否处于离线状态(如热插拔移除后)。

struct device 是Linux设备模型的核心结构体,它抽象了系统中所有物理或逻辑设备的通用属性和行为。通过层次化结构(parent)、总线关联(bus)、驱动绑定(driver)和资源管理(DMA、电源、中断等),实现了设备的统一管理。其设计支持动态设备发现、热插拔、跨平台兼容性,是驱动开发者和内核管理硬件的基础框架。

核心关系概述

总线作为平台,设备作为硬件实体,驱动作为软件控制者,三者形成”总线承载设备,驱动控制设备”的协作模式。

Tags:

No responses yet

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注