驱动中的device和device_driver结构体

embedded/2024/10/18 22:54:40/

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 thisdevice */void		*platform_data;	/* Platform specific data, devicecore doesn't touch it */void		*driver_data;	/* Driver data, set and get withdev_set/get_drvdata */struct dev_links_info	links;struct dev_pm_info	power;struct dev_pm_domain	*pm_domain;#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAINstruct irq_domain	*msi_domain;
#endif
#ifdef CONFIG_PINCTRLstruct dev_pin_info	*pins;
#endif
#ifdef CONFIG_GENERIC_MSI_IRQstruct list_head	msi_list;
#endif#ifdef CONFIG_NUMAint		numa_node;	/* NUMA node this device is close to */
#endifu64		*dma_mask;	/* dma mask (if dma'able device) */u64		coherent_dma_mask;/* Like dma_mask, but foralloc_coherent mappings asnot all hardware supports64 bit addresses for consistentallocations 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 memoverride */
#ifdef CONFIG_DMA_CMAstruct cma *cma_area;		/* contiguous memory area for dmaallocations */
#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;
};

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;
};

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

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总线,关于总线和平台设备具体的会另开文章讲解。


http://www.ppmy.cn/embedded/123689.html

相关文章

探索基于基于人工智能进行的漏洞评估的前景

根据2023年的一份报告 网络安全企业据估计,到 10.5 年,网络犯罪每年将给世界造成 2025 万亿美元的损失。每年记录在案的网络犯罪数量都会创下新高。这要求对传统的安全测试流程进行重大改变。这就是漏洞评估发挥作用的地方。 漏洞评估对于识别系统中的弱…

毕业设计选题:基于ssm+vue+uniapp的医院管理系统小程序

开发语言:Java框架:ssmuniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:M…

计算机视觉算法知识详解(含代码示例)

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…

【系统架构设计师】专题:基于构件的软件工程考点

更多内容请见: 备考系统架构设计师-核心总结目录 文章目录 一、构件概述二、构件模型三、CBSE的特征四、CBSE的过程五、构件组装一、构件概述 基于构件的软件工程(Component-Based Software Engineering,CBSE) 是一种基于分布对象技术、 强调通过可复用构件设计与构造软件系…

0基础学前端 day9--css布局

CSS布局概述 一、引言 CSS布局是Web开发中至关重要的一部分,用于控制网页元素的排列和显示方式。不同的布局技术被应用于网页设计中,以确保其在各种设备和屏幕尺寸上都具有良好的用户体验。CSS布局技术包括浮动(float)、定位&am…

Redis: Sentinel哨兵监控架构及环境搭建

概述 在主从模式下,我们通过从节点只读模式提高了系统的并发能力并发不断增加,只需要扩展从节点即可,只要主从服务器之间,网络连接正常主服务器就会将写入自己的数据同步更新给从服务器,从而保证主从服务器的数据相同…

Rust Web自动化Demo

1.新建项目 使用RustCover新建项目,目录如下: Cargo.toml文件 [package] name "Demo" version "0.1.0" edition "2021"[dependencies] tokio { version "1", features ["full"] } thirtyfour…

vite学习教程04、vue集成axios封装request工具类及应用

文章目录 前言1、安装axios2、封装request工具类3、封装api请求工具4、实战:vue中使用api请求工具类资料获取 前言 博主介绍:✌目前全网粉丝3W,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技…