Linux设备模型-总线

279 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第6天,点击查看活动详情

在2.5版本之前,内核无法描述和管理对象,代码的可重用性没有像现在这样得到增强。换句话说,既没有设备拓扑,也没有组织。没有关于子系统关系的信息,也没有关于系统组织的信息。这就引入了Linux设备模型(LDM)。

  • 类的概念,对相同类型的设备或提供相同功能的设备进行分组(如鼠标和键盘都是输入设备)。
  • 通过名为sysfs的虚拟文件系统与用户空间进行通信,以便用户空间管理和枚举设备及其公开的属性。
  • 管理对象生命周期,使用引用计数(在管理资源中大量使用)。
  • 电源管理,以处理设备关闭的顺序。
  • 代码的可重用性。类和框架提供接口,就像合约一样,任何向它们注册的驱动程序都必须遵守。
  • LDM在内核中引入了面向对象(OO)的编程风格。

总线

总线是设备和处理器之间的通道链路。管理总线并将其协议输出到设备的硬件实体称为总线控制器。例如,USB控制器提供USB支持,I2C控制器提供I2C总线支持。因此,自身作为设备的总线控制器必须像任何设备那样注册。它是总线上设备的父设备。换句话说,位于总线上的每个设备都必须使其父域指向总线设备。总线在内核中由struct bus_type结构表示:

struct bus_type { 
   const char *name; 
   const char *dev_name; 
   struct device *dev_root; 
   struct device_attribute  *dev_attrs; /* 使用dev_groups代替*/ 
   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 (*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 dev_pm_ops *pm; 
 
   struct subsys_private *p; 
   struct lock_class_key lock_key; 
};

结构中各元素的含义如下。

  • match:回调,每当新设备或驱动程序添加到总线中时调用它。回调必须足够智能,在设备和驱动程序之间存在匹配的情况下返回非零值,两者都作为参数给出。match回调的主要目的是让总线确定某个设备能否由指定的驱动程序或其他逻辑处理,以及指定的驱动程序是否支持某个设备。大多数情况下,验证通过简单的字符串(设备和驱动程序名称, 表格和DT兼容的属性)比较来实现。对于枚举设备(PCI、USB),验证通过将驱动程序支持的设备ID与指定设备的设备ID进行比较来实现,而不会牺牲总线特定的功能。

  • probe:回调,在新设备或驱动程序添加到总线,并且匹配发生后调用它。该函数负责分配特定的总线设备结构,调用指定驱动程序的probe函数,它管理该设备(之前分配)。

  • remove:当设备从总线上移除时调用它。

  • suspend:总线上的设备需要进入睡眠模式时调用此方法。

  • resume:总线上的设备退出睡眠模式时调用此方法。

  • pm:这是一组总线电源管理操作,它将调用指定设备驱动程序的pm-ops

  • drv_groups:这个指针指向struct attribute_group元素列表(数组),其中每个元素都有一个指针指向struct attribute列表(数组)。它表示总线上设备驱动程序的默认属性。传递给该字段的属性将会被发送给该总线上注册的每个驱动程序。这些属性可以在/sys/bus//drivers/ 内的驱动程序目录下找到

  • dev_groups:表示总线上设备的默认属性。(通过struct attribute_group元素的列表/数组)传递给该字段的属性将会被发送给总线上注册的每个设备。这些属性可以在/sys/bus//devices/内的设备目录中找到。

  • bus_group:保存一套(组)默认属性,总线注册到内核时,自动添加这组默认属性。

    除定义bus_type之外,总线控制器驱动程序还必须定义总线特定的驱动程序结构和总线特定的设备结构,前者扩展通用struct device_driver结构,后者扩展通用struct device结构,二者是设备模型核心的两个部分。总线驱动程序还必须为探测发现的每个物理设备分配总线特定的设备结构,并负责初始化设备的bus和parent字段,向LDM内核注册设备。这些字段必须指向总线驱动程序中定义的总线设备和bus_type结构。LDM内核用它构建设备层次结构并初始化其他字段。

在这个例子中定义两个辅助宏,用给定的通用struct device和struct driver获取packt设备和packt驱动程序: