首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

驱动中的device和device_driver结构体

  • 25-03-04 14:02
  • 3981
  • 7248
blog.csdn.net

device和device driver是Linux驱动开发的基本概念。Linux kernel的思路很简单:驱动开发,就是要开发指定的软件(driver)以驱动指定的设备,所以kernel就为设备和驱动它的driver定义了两个数据结构,分别是device和device_driver。

1. struct device

/**
 * struct device - The basic device structure
 * @parent:	The device's "parent" device, the device to which it is attached.
 * 		In most cases, a parent device is some sort of bus or host
 * 		controller. If parent is NULL, the device, is a top-level device,
 * 		which is not usually what you want.
 * @p:		Holds the private data of the driver core portions of the device.
 * 		See the comment of the struct device_private for detail.
 * @kobj:	A top-level, abstract class from which other classes are derived.
 * @init_name:	Initial name of the device.
 * @type:	The type of device.
 * 		This identifies the device type and carries type-specific
 * 		information.
 * @mutex:	Mutex to synchronize calls to its driver.
 * @bus:	Type of bus device is on.
 * @driver:	Which driver has allocated this
 * @platform_data: Platform data specific to the device.
 * 		Example: For devices on custom boards, as typical of embedded
 * 		and SOC based hardware, Linux often uses platform_data to point
 * 		to board-specific structures describing devices and how they
 * 		are wired.  That can include what ports are available, chip
 * 		variants, which GPIO pins act in what additional roles, and so
 * 		on.  This shrinks the "Board Support Packages" (BSPs) and
 * 		minimizes board-specific #ifdefs in drivers.
 * @driver_data: Private pointer for driver specific info.
 * @power:	For device power management.
 * 		See Documentation/power/devices.txt for details.
 * @pm_domain:	Provide callbacks that are executed during system suspend,
 * 		hibernation, system resume and during runtime PM transitions
 * 		along with subsystem-level and driver-level callbacks.
 * @pins:	For device pin management.
 *		See Documentation/pinctrl.txt for details.
 * @msi_list:	Hosts MSI descriptors
 * @msi_domain: The generic MSI domain this device is using.
 * @numa_node:	NUMA node this device is close to.
 * @dma_mask:	Dma mask (if dma'ble device).
 * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all
 * 		hardware supports 64-bit addresses for consistent allocations
 * 		such descriptors.
 * @dma_pfn_offset: offset of DMA memory range relatively of RAM
 * @dma_parms:	A low level driver may set these to teach IOMMU code about
 * 		segment limitations.
 * @dma_pools:	Dma pools (if dma'ble device).
 * @dma_mem:	Internal for coherent mem override.
 * @cma_area:	Contiguous memory area for dma allocations
 * @archdata:	For arch-specific additions.
 * @of_node:	Associated device tree node.
 * @fwnode:	Associated device node supplied by platform firmware.
 * @devt:	For creating the sysfs "dev".
 * @id:		device instance
 * @devres_lock: Spinlock to protect the resource of the device.
 * @devres_head: The resources list of the device.
 * @knode_class: The node used to add the device to the class list.
 * @class:	The class of the device.
 * @groups:	Optional attribute groups.
 * @release:	Callback to free the device after all references have
 * 		gone away. This should be set by the allocator of the
 * 		device (i.e. the bus driver that discovered the device).
 * @iommu_group: IOMMU group the device belongs to.
 * @iommu_fwspec: IOMMU-specific properties supplied by firmware.
 *
 * @offline_disabled: If set, the device is permanently online.
 * @offline:	Set after successful invocation of bus type's .offline().
 *
 * At the lowest level, every device in a Linux system is represented by an
 * instance of struct device. The device structure contains the information
 * that the device model core needs to model the system. Most subsystems,
 * however, track additional information about the devices they host. As a
 * result, it is rare for devices to be represented by bare device structures;
 * instead, that structure, like kobject structures, is usually embedded within
 * a higher-level representation of the device.
 */
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_links_info	links;
	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;
	struct iommu_fwspec	*iommu_fwspec;

	bool			offline_disabled:1;
	bool			offline:1;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150

struct device 是 Linux 设备模型中用于描述设备的基础结构体,包含设备驱动程序中几乎所有的关键信息。这个结构体的每个成员都代表设备的不同属性或控制与管理功能。

主要成员变量

  1. struct device *parent
    • 设备的父设备指针。大多数情况下,父设备是某种总线或控制器(如 PCI 控制器)。如果为 NULL,则表示该设备是顶层设备。
  2. struct device_private *p
    • 保存设备私有数据的指针,用于设备模型核心管理设备的内部数据。通常开发者不直接操作这个字段。
  3. struct kobject kobj
    • kobject 是 Linux 内核中的一种对象管理机制,kobj 用于在 /sys 文件系统中表示设备,通过它可以导出设备的属性到用户空间。
  4. const char *init_name
    • 设备的初始名称,用于在注册时给设备指定名称。
    • 注1:在设备模型中,名称是一个非常重要的变量,任何注册到内核中的设备,都必须有一个合法的名称,可以在初始化时给出,也可以由内核根据“bus name + device ID”的方式创造。
  5. const struct device_type *type
    • 设备类型指针,定义了设备的类型及其类型特定信息。
  6. struct mutex mutex
    • 设备互斥锁,用于同步对该设备的操作,避免多个线程同时访问设备驱动的共享资源时引发冲突。
  7. struct bus_type *bus
    • 指向设备所在的总线类型(如 PCI、I2C、SPI 等)的指针,用于描述设备属于哪个总线。这里要留意一下,后面会讲到平台总线
  8. struct device_driver *driver
    • 指向分配该设备的驱动程序结构体的指针,表示当前哪个驱动程序在控制这个设备。
  9. void *platform_data
    • 平台相关的数据指针。对于嵌入式或 SoC 硬件,platform_data 通常指向特定设备的硬件配置数据,例如可用的端口、芯片变体等。它帮助减少驱动程序中的板级特定代码。
  10. void *driver_data
    • 驱动程序的私有数据,驱动可以通过 dev_set_drvdata() 和 dev_get_drvdata() 来设置和获取该字段。
  11. struct dev_links_info links
    • 存储与设备之间的拓扑关系信息,如设备间的依赖性。
  12. struct dev_pm_info power
    • 设备电源管理信息。包含电源状态、挂起、恢复等操作相关的字段,涉及设备的电源管理。
  13. struct dev_pm_domain *pm_domain
    • 设备电源管理域的指针,定义系统挂起、休眠、恢复时需要执行的回调函数。
  14. struct irq_domain *msi_domain
    • 当设备使用 Message Signaled Interrupts (MSI) 时,指向管理设备 MSI 中断的域。
  15. struct dev_pin_info *pins
    • 引脚管理信息,设备在引脚控制方面的数据结构,用于 GPIO 和 pinctrl 子系统。
  16. struct list_head msi_list
    • 保存设备的 MSI 描述符的链表头。
  17. int numa_node
    • 设备所在的 NUMA(Non-Uniform Memory Access)节点。
  18. u64 *dma_mask
    • DMA 掩码,用于描述设备支持的 DMA 地址范围。设备使用 DMA 时,用来表示设备能够访问的物理内存地址空间的最大范围。
  19. u64 coherent_dma_mask
    • 与 dma_mask 类似,但专门用于一致性内存的 DMA 掩码。
  20. unsigned long dma_pfn_offset
    • DMA 内存与物理内存之间的偏移量。
  21. struct device_dma_parameters *dma_parms
    • DMA 参数,低层驱动可以通过它告知 IOMMU 关于段限制等特性。
  22. struct list_head dma_pools
    • 设备的 DMA 池列表头,表示设备的 DMA 内存池。
  23. struct dma_coherent_mem *dma_mem
    • 用于管理一致性 DMA 内存的内部数据结构。
  24. struct cma *cma_area
    • 用于 DMA 分配的连续内存区域指针。
  25. struct dev_archdata archdata
    • 设备的体系结构特定数据。不同平台可以利用这个字段扩展额外的体系结构相关的信息。
  26. struct device_node *of_node
    • 指向与设备相关的设备树节点。对于使用设备树的系统,of_node 记录设备在设备树中的描述信息。
  27. struct fwnode_handle *fwnode
    • 设备的固件节点,通常用于指向 ACPI 或设备树中的设备描述。
  28. dev_t devt
    • 设备的 dev_t 类型,设备号,表示设备的主设备号和次设备号,用于创建设备节点。
  29. u32 id
    • 设备实例 ID,用于标识同类设备的不同实例。
  30. spinlock_t devres_lock
    • 设备资源锁,用于保护设备的资源列表。
  31. struct list_head devres_head
    • 设备资源链表头,记录与设备相关的资源(如内存、I/O 端口等)。
  32. struct klist_node knode_class
    • 用于将设备添加到设备类链表中的节点。
  33. struct class *class
    • 设备的类,用于分类设备(如输入设备、网络设备等)。设备类定义设备的行为及其属性。
  34. const struct attribute_group **groups
    • 可选的属性组,用于定义设备在 /sys 文件系统中暴露的额外属性。
  35. void (*release)(struct device *dev)
    • 设备的释放回调函数,当所有对设备的引用都释放后,调用该函数释放设备占用的资源。
  36. struct iommu_group *iommu_group
    • 设备所属的 IOMMU 组指针。IOMMU 组用于管理设备之间的内存隔离。
  37. struct iommu_fwspec *iommu_fwspec
    • 由固件提供的 IOMMU 特定属性。

状态标志位

  1. bool offline_disabled:1
    • 标志位,指示设备是否永久在线,如果设置为 true,设备无法进入离线状态。
  2. bool offline:1
    • 标志位,指示设备是否离线。

struct device 是 Linux 设备模型中非常重要的结构体,负责设备的管理与控制。它包含了设备在总线上的位置信息、与驱动程序的关联、DMA 信息、电源管理、IOMMU 等多种设备相关的属性。在实际使用时,struct device 通常是被嵌入到更高级的设备结构中,用于表示具体的硬件设备,比如平台platfrom_device结构体中。其实这些成员内核开发者也给了详细的注解。

2. struct device_driver

/**
 * struct device_driver - The basic device driver structure
 * @name:	Name of the device driver.
 * @bus:	The bus which the device of this driver belongs to.
 * @owner:	The module owner.
 * @mod_name:	Used for built-in modules.
 * @suppress_bind_attrs: Disables bind/unbind via sysfs.
 * @probe_type:	Type of the probe (synchronous or asynchronous) to use.
 * @of_match_table: The open firmware table.
 * @acpi_match_table: The ACPI match table.
 * @probe:	Called to query the existence of a specific device,
 *		whether this driver can work with it, and bind the driver
 *		to a specific device.
 * @remove:	Called when the device is removed from the system to
 *		unbind a device from this driver.
 * @shutdown:	Called at shut-down time to quiesce the device.
 * @suspend:	Called to put the device to sleep mode. Usually to a
 *		low power state.
 * @resume:	Called to bring a device from sleep mode.
 * @groups:	Default attributes that get created by the driver core
 *		automatically.
 * @pm:		Power management operations of the device which matched
 *		this driver.
 * @p:		Driver core's private data, no one other than the driver
 *		core can touch this.
 *
 * The device driver-model tracks all of the drivers known to the system.
 * The main reason for this tracking is to enable the driver core to match
 * up drivers with new devices. Once drivers are known objects within the
 * system, however, a number of other things become possible. Device drivers
 * can export information and configuration variables that are independent
 * of any specific device.
 */
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;
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

struct device_driver 是 Linux 内核中用于描述设备驱动程序的基本结构体,它用于表示设备驱动的属性和操作。该结构体负责跟踪系统中已知的所有驱动程序,并为新设备和驱动程序之间进行匹配提供基础。

主要成员变量

  1. const char *name
    • 驱动程序的名称。在设备和驱动之间进行匹配时,设备的名称和驱动的名称会进行比较。
  2. struct bus_type *bus
    • 驱动程序所依附的总线类型。每个驱动程序都属于某个总线类型,例如 PCI、I2C、SPI 等。
  3. struct module *owner
    • 模块的所有者,指向实现该驱动的模块(内核模块)结构体。它确保驱动所在模块在使用期间不会被卸载。
  4. const char *mod_name
    • 模块的名称。对于内建模块(built-in modules),这个字段用于指明模块的名字。
  5. bool suppress_bind_attrs
    • 控制是否通过 sysfs 禁止手动绑定/解绑设备。如果设置为 true,则无法通过 /sys 文件系统中的 bind 和 unbind 文件手动进行设备和驱动的绑定/解绑。
  6. enum probe_type probe_type
    • 控制驱动程序的 probe 操作的类型,可以是同步的(synchronous)或异步的(asynchronous)。它决定了驱动程序在处理设备时,probe 函数是阻塞执行还是非阻塞执行。
  7. const struct of_device_id *of_match_table
    • 用于设备树(Device Tree)的匹配表。驱动程序可以通过该表与设备树中的设备节点进行匹配。
  8. const struct acpi_device_id *acpi_match_table
    • 用于 ACPI(高级配置与电源接口)的匹配表。驱动程序通过该表与系统的 ACPI 表进行匹配,从而识别设备。

驱动操作接口

  1. **int (*probe)(struct device *dev)**** **
    • probe 函数用于在设备检测到时调用,它用于检查该驱动是否可以支持指定的设备,并在可以支持时绑定设备和驱动。返回 0 表示成功,非零表示失败。
    • 所谓的"probe”,是指在Linux内核中,如果存在相同名称的device和device_driver(注:还存在其它方式),内核就会执行device_driver中的probe回调函数,而该函数就是所有driver的入口,可以执行诸如硬件设备初始化、字符设备注册、设备文件操作ops注册等动作。
    • 这里先不讲,在bus中再提
  2. int (*remove)(struct device *dev)
    • 当设备被从系统中移除时调用,用于解除设备与驱动的绑定并释放相关资源。通常在卸载设备时调用。
  3. void (*shutdown)(struct device *dev)
    • 系统关闭时调用,用于关闭设备并确保其处于安静状态。这通常在系统关机或重启时调用。
  4. int (*suspend)(struct device *dev, pm_message_t state)
    • 将设备挂起(进入低功耗模式)时调用。挂起操作通常在设备空闲或系统进入休眠模式时触发。
  5. int (*resume)(struct device *dev)
    • 将设备从挂起状态恢复到正常运行状态时调用,通常在系统恢复时或设备被再次使用时调用。

其他成员

  1. const struct attribute_group **groups
    • 驱动程序导出的默认属性组。内核会自动创建这些属性组,使驱动程序可以将配置或状态信息通过 /sys 文件系统提供给用户空间。
  2. const struct dev_pm_ops *pm
    • 设备电源管理操作的指针。通过该指针,驱动程序可以定义设备的电源管理操作(如挂起、恢复、系统睡眠等)。
  3. struct driver_private *p
    • 驱动程序核心的私有数据字段。只有驱动程序核心可以访问该字段,通常开发者不需要直接使用这个字段。

struct device_driver 是 Linux 驱动模型中用于描述设备驱动程序的核心结构体,它定义了驱动程序的各种操作接口(如 probe、remove、shutdown、suspend、resume 等),并包含了一些驱动程序的元数据(如名称、所属总线类型、匹配表等)。通过这个结构体,驱动程序可以被内核识别,并通过合适的接口与设备进行绑定、控制和管理。

3. 驱动开发的基本步骤

设备模型框架下,设备驱动的开发是一件很简单的事情,主要包括2个步骤:

步骤1:分配一个struct device类型的变量,填充必要的信息后,把它注册到内核中。

步骤2:分配一个struct device_driver类型的变量,填充必要的信息后,把它注册到内核中。

完成这两步,内核会在何时的时机对他们进行匹配,当然匹配的前提是这两个结构体中的name是相同的(同一bus的情况下)

但是,一般情况下,Linux驱动开发很少直接使用device和device_driver,因为内核在它们之上又封装了一层,如soc device、platform device等等,而这些层次提供的接口更为简单、易用(也正是因为这个原因,并不会过多涉及device、device_driver等模块的实现细节)。

就比如platform device,很多情况下不需要我们自己去填充,只需要在设备树(后续会讲)中去定义好设备的相关信息(寄存器?中断资源?引脚?),平台就会自己帮我们注册号platform device。而platform其实依靠的也是bus总线,关于总线和平台设备具体的会另开文章讲解。

注:本文转载自blog.csdn.net的憧憬一下的文章"https://blog.csdn.net/caiji0169/article/details/142714413"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top