linux设备驱动的代码结构,阅读Linux设备驱动模型源码之 device结构体成员详解

【前言】

我们学习 Linux 设备驱动,很多人在一开始往往急于想找到快速入门的方法,希望能有一个提纲挈领的使用说明来帮助我们快速理解 Linux 设备驱动的设计思路和框架,从而摆脱掉 Linux 内核这头庞然怪兽。我自己最初也是这样。然而事与愿违,如果学习 Linux 设备驱动能有这样的捷径让大多数人快速掌握,那么具备开发 Linux 设备驱动的能力也就变得不再值钱了。所以,学习 Linux 设备驱动的正道还是丢掉世俗的浮躁、静下心来好好阅读内核源码。正如 Linus Torvalds 的神谕那样,“Read the fucking source code”。我想,这也是做好其它事情的不二法门。

在这种想法的指引下,在前一阵子对 platform 驱动模型、i2c 驱动模型、ASoC 驱动模型、kobject+kset+ktype 有了大体认识之后,我再次开始阅读内核中的设备驱动框架代码。说实话,代码中的注释有的时候比我们在书上或网上看到的讲解更加清晰直观。我把 device 结构体的官方注释翻译成了中文写在下面。

【device结构体成员详解】

/**

* device 结构体 - 设备驱动模型中的基础结构体之一

* @parent:设备所依附的“父设备”。

* 大多数情况下,这样的父设备是某种总线或主控制器。

* 如果该成员变量的值为 NULL 表示当前设备是一个最“顶端”设备,

* 通常这样的设备都不是你想得到的那个。

* @p:该成员变量是一个指向设备结构体中驱动内核部分的私有数据的指针。

* 更详细的信息可以阅读 device_private 结构体的注释。

* @kobj:kobj是最“顶层”的抽象类,所有其它的类都继承自它。

* @init_name:设备结构体所对应的设备的名称。

* @type:设备结构体所对应的设备的类型。

* 该成员变量用于标识设备类型,并存储着该类型设备特有的信息。

* @mutex:用于同步驱动中的函数调用的互斥锁。

* @bus:设备所挂接的总线的类型。

* @driver:该成员变量指向开辟当前设备结构体空间的设备驱动。

* @platform_data: 该成员变量用于保存和设备硬件相关的平台数据。

* 示例:对于自定义电路板上的设备来说,典型的情况譬如嵌入式设备

* 以及一些基于 SOC 的硬件,Linux 系统通常会使用 platform_data 指针指向

* 与电路板硬件相关的结构体,这些结构体中的成员描述了它们对应的设备硬件资源

* 以及电路板的电路连接情况。这些被描述的内容可以包括芯片的哪些端口可用,与

* 上一代芯片相比有什么改动,哪个 GPIO 引脚有额外的功能等等。

* 这个成员变量的实现使得 BSP 的工作量减小了许多,

* 同时也减少了我们为兼容不同的电路板而写的 #ifdefs 语句的数量。

* @driver_data: 指向驱动特定信息的私有指针。

* @power:用于设备的电源管理。

* 更详细的信息可以阅读 Documentation/power/devices.txt 文档。

* @pm_domain:为设备提供当系统被挂起、

* 休眠、唤醒和电源状态切换时的回调函数,

* 以及子系统级别和驱动级别的回调函数。

* @pins:用于设备引脚管理。

*更详细的信息可以阅读 Documentation/pinctrl.txt 文档。

* @msi_list:主机 MSI 描述符。

* @msi_domain: 设备结构体所使用的 MSI 域。

* @numa_node:与设备结构体最邻近的 NUMA 节点。

* @dma_mask:DMA掩码(前提是当前设备可进行 DMA 操作)。

* @coherent_dma_mask: 作用和 dma_mask 类似,用于一致性 DMA 地址映射。因为并不是所有

* 硬件都支持在 64 位地址下开辟连续的内存空间。

* @dma_pfn_offset: DMA区域范围在内存中的地址偏移量。

* @dma_parms:一个低权限级别的驱动会通过这个成员变量告知 IOMMU 代码关于

* 段操作限制相关的规则。

* @dma_pools:指向 DMA池 的指针(前提是当前设备可进行 DMA 操作)。

* @dma_mem:一致性 DMA 的可读写区域。

* @cma_area:DMA区域中的连续内存空间。

* @archdata:芯片架构相关的内容。

* @of_node:设备所在设备树的节点。

* @fwnode:平台固件对应的设备树节点。

* @devt:用于在 sysfs 中创建设备文件。

* @id:设备实例(ID 编号)。

* @devres_lock: 用于保护设备上的资源访问的自旋锁。

* @devres_head: 设备上的资源列表。

* @knode_class: 用于将当前设备加入到类列表的节点。

* @class:设备所属的类。

* @groups:设备的属性集合(可选)。

* @release:当设备的引用计数减少为 0 时,使用该成员变量所指向的析构函数

* 释放当前设备结构体。这个成员变量的值应该由当前设备的创建者进行

* 设置(比如成功找到设备的总线驱动)。

* @iommu_group: 设备所属的 IOMMU 集合。

*

* @offline_disabled: 如果这个成员变量的值被置 1,则设备将处于永远在线状态。

* @offline:如果总线类型所辖的 offline() 函数被成功调用,则该成员变量的值将被置 1。

*

* 在最底层级别,Linux系统中的每个设备都被一个 device 结构体的

* 实例所表示。device 结构体中包含了设备模型内核在描述系统结构时

* 所需要的信息。大多数子系统在此基础上还会查找它们下属设备的额外信息。

* 这导致我们很难用少数 device 结构体来表示设备的所有信息,所以通常

* 还会配合 kobject 结构体来描述设备的更高层信息。

*/

struct device {

struct device*parent;

struct device_private*p;

struct kobject kobj;

const char*init_name; /* 设备的初始化名称 */

const struct device_type *type;

struct mutexmutex;/* 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_infopower;

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

#endif

#ifdef CONFIG_NUMA

intnuma_node;/* NUMA node this device is close to */

#endif

u64*dma_mask;/* dma mask (if dma'able device) */

u64coherent_dma_mask;/* Like dma_mask, but for

alloc_coherent mappings as

not all hardware supports

64 bit addresses for consistent

allocations such descriptors. */

unsigned longdma_pfn_offset;

struct device_dma_parameters *dma_parms;

struct list_headdma_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_archdataarchdata;

struct device_node*of_node; /* associated device tree node */

struct fwnode_handle*fwnode; /* firmware device node */

dev_tdevt;/* dev_t, creates the sysfs "dev" */

u32id;/* device instance */

spinlock_tdevres_lock;

struct list_headdevres_head;

struct klist_nodeknode_class;

struct class*class;

const struct attribute_group **groups;/* optional groups */

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

struct iommu_group*iommu_group;

booloffline_disabled:1;

booloffline:1;

};

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux设备驱动开发详解4.0码》是一本深入介绍Linux设备驱动开发的书籍,主要讲解Linux内核4.0版本的设备驱动开发原理和实践经验。该书通过详细剖析Linux内核码,深入解读设备驱动的核心概念和原理,帮助读者深入理解Linux设备驱动开发的内部机制。 首先,该书介绍了Linux内核的基本概念和架构,帮助读者建立起对Linux内核的整框架的理解。然后,逐步深入介绍了设备驱动的原理和开发过程,包括设备驱动和总线的概念、设备树的使用、中断处理、内存管理等关键内容。 该书通过具的案例分析,讲解了设备驱动的编写过程和常见的开发技巧。其中涉及了字符设备驱动、块设备驱动和网络设备驱动等多个方面的内容,为读者提供了丰富的实践经验。此外,该书还介绍了Linux设备模型设备树和ACPI等新技术的应用,帮助读者了解最新的设备驱动开发趋势和技术。 本书的特点是以实践为导向,通过对内核码的解析和案例分析,让读者更加深入地理解和掌握设备驱动开发的技术细节。同时,作者还提供了大量的代码示例和调试技巧,帮助读者解决实际开发中常遇到的问题。 总之,《Linux设备驱动开发详解4.0码》是一本深入而全面的设备驱动开发指南,适合具有一定Linux基础的读者学习和参考。通过系统学习该书,读者可以深入了解Linux内核的设备驱动开发原理,提高自己的设备驱动开发能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值