Linux 设备驱动模型

438 阅读6分钟

简介

Linux操作系统在kernel 2.6版本中引入了设备驱动模型,简化驱动程序的编写。

Linux的设备驱动模型是为了支持设备的即插即用功能,为了减少冲突,需要具备以下条件:

  • 自动检测在系统中添加/删除设备
  • 资源管理(地址,IRQ中断,DMA通道,内存区域)
  • 操作系统可以自动加载新设备的驱动程序
  • 当设备和总线允许时,不需要进行系统重启(热插拔)

驱动模型主要包括如下基本结构

  • 设备 (struct device)
  • 总线 (struct bus_type)
  • 类 (struct class)
  • 驱动 (struct driver)
  • 子系统(struct sub_system)

sysfs文件系统

sysfs目录下主要分为如下划分

image.png

  • block 系统中有各种块设备(磁盘,分区)
  • bus 物理设备链接到总线上(pci, ide, usb)
  • class 系统中可用的驱动程序类别(net, block, tty, rtc, graphics)
  • dev 链接到系统的设备的层次结构
  • firmare 来自系统固件的信息
  • fs 已经挂载的文件系统信息
  • hypervisor 虚拟化信息
  • kernel 内核状态信息(已经登陆用户信息,热插拔)
  • module当前内核已经加载的内核模块
  • power 与电源管理子系统的相关的信息

kset and kobject

参考文档:The zen of kobjects

源码文件:

include/linux/kobject.h include/linux/kref.h lib/kobject.c

 

kobject的结构体如下所示

struct kobject {
    const char      *name;                                  // 挂载sysfs中对应的目录名称
    struct list_head    entry;                              // 属于某个kset, kset中有这个列表
    struct kobject      *parent;                            // kobject的父亲结构,形成层次结构,在sysfs中形成目录关系
    struct kset     *kset;                                  // 当前的kobject属于那个kset
    struct kobj_type    *ktype;                             // kobject的类型,主要是命名空间,操作函数
    struct kernfs_node  *sd; /* sysfs directory entry */    // 对应的sysfs对象,在3.14以后sysfs基于kernelfs实现
    struct kref     kref;                                   // 引用计数
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
    struct delayed_work release;
#endif
    unsigned int state_initialized:1;                       // 是否初始化
    unsigned int state_in_sysfs:1;                          // 是否已经注册到sysfs中
    unsigned int state_add_uevent_sent:1;                   // 是否已经发送KOBJ_ADD uevent消息
    unsigned int state_remove_uevent_sent:1;                // 是否已经发送KOBJ_REMOVE uevent消息
    unsigned int uevent_suppress:1;                         // 是否不通知uevent消息

};

Kset的结构体代码如下所示

struct kset {
    struct list_head list;                          // 列表,主要用于存储属于这个kset的kobject.
    spinlock_t list_lock;                           // 列表访问锁
    struct kobject kobj;                            // kobject kset也可以被当作一个kset
    const struct kset_uevent_ops *uevent_ops;       // kset uevent操作接口
} __randomize_layout;

从上方的结构中我们可以看到kset是一个用于存储kobject的容器,但是kset本身也是一个kobject.

思考

为什么kset中也需要一个kobject类型?

Linux内核模型中主要将设备与sysfs相结合,kset充当的更多的类型目录的职能,kobject更多的是文件的功能.

为什么在kobject中还需要提供一个parent指针?

上方的kset的管理职能更多的是面向用户访问的sysfs的文件职能,但是kobject在内核中需要有自己的管理结构,利用parent指针,构造kobject按层级访问的方式,能够有效的完成kobject的管理.

parent的管理方式带来了什么样的便利?

parent可以用于管理属于class的关系,后面的device和class的关系我们会详细描述

kobject 和kset模型结构如下所示

image.png

kset中有部分的uevent操作

struct kset_uevent_ops {
    int (* const filter)(struct kset *kset, struct kobject *kobj);
    const char *(* const name)(struct kset *kset, struct kobject *kobj);
    int (* const uevent)(struct kset *kset, struct kobject *kobj,
              struct kobj_uevent_env *env);
};

在进行uevent操作时,上方提供的函数接口可能会被执行

  • filter 主要用于过滤部分的kobject,不需要进行uevent操作的上报
  • name 将字符串传递给用户空间的热插拔程序处理
  • uevent 将用户空间需要的参数转换成环境变量

uevent的常见操作: image.png

总线 class设备与驱动

参考文档: linux-kernel-labs.github.io/refs/pull/1…

核心代码driver/base分析 Linux下为什么需要设计出总线,设备与驱动这三者之间的一个抽象存在,目的是什么?

首先聊一下驱动与设备的分离,实际上这个是符合Unix设计原则中的机制与策略分离的原则,只不过这里的机制是指驱动,也就是提供的各种操作接口,策略就是指设备,也就是我们的各种操作设备,也就是各种被操作的实体(如寄存器,中断,内存地址等)。

为什么又引入了总线的概念?

抛开计算机的设计本来就有总线的概念,设备都是挂载在总线不同的总线上的,利用总线可以有效的将设备进行分类(但是针对目前的设计,需要引入总线的概念还是远远不用的,因为驱动和设备已经是可以逐一配对的)。这里又需要考虑到Linux的另外两种机制:1. 模块机制 2. 设备热插拔机制,因为模块机制允许驱动被后来加载,也就是设备可能已经挂载在系统上,但是由于没有驱动,设备无法运转,这时需要驱动与设备进行配对,配对完成后,驱动设备正常工作。热插拔机制是允许设备动态加载,本来驱动已经在系统中,设备后续加载后,需要驱动与设备进行配对,配对完成后,驱动设备正常工作。综上所述,那么需要管理者来管理系统中所有注册的驱动和设备,那么这个管理者正好又根据计算机的总线模型(设备都挂载在不同的总线下)对设备进行分类,有效的减少全局匹配驱动与设备的次数。

为什么需要加入class的设计?

参考上方的设计,目前已经满足了驱动的功能要求,但是目前的实现对用户不太友好,因为通常我们期望可以通过功能找到相关的设备,如我们期望找到硬盘时,我们并不关心硬盘下层是挂载在SATA,mSATA, m.2, PCIe的总线上,我们期望的是根据功能找到相关的设备,这时候class应运而出。正好与sysfs文件系统结合,给上层用户提供相关的操作接口。

为什么需要引入platform_bus和platform_device?

在操作系统中可能存在某些设备不是通过总线CPU相连,肯恩是直接挂载在某些GPIO(相当于一个pin脚)下,所以系统中会存在一些不存在总线的bus和设备。

加入了总线的概念,那么我们了解一下系统中都有哪些总线,我们可以在/sys/bus目录下找到 通过命令tree -L 1获取到以下信息

image.png

整体图如下,之前搜集的时候忘了是从哪位同仁中copy过来,如有侵权,请联系我删除。

image.png