当前位置: 亚洲城ca88 > 亚洲城 > 正文

linux设备模型详解,归纳介绍Linux统1器械为主组织

时间:2019-06-01 11:32来源:亚洲城
Linux设备模型是对系统设备协会架构实行抽象的2个数据结构,目的在于为器材驱动举行分层、分类、组织。下落设备各个性带来的Linux驱动开辟的复杂度,以及配备热拔插管理、电源管

Linux设备模型是对系统设备协会架构实行抽象的2个数据结构,目的在于为器材驱动举行分层、分类、组织。下落设备各个性带来的Linux驱动开辟的复杂度,以及配备热拔插管理、电源管理等。

linux设备模型详解

透过长日子读书Linux统1器材,于是和豪门分享一下,看完本文你势必有大多取得,希望本文能教会你越多东西。在 Linux 二.5内核的付出进度中,大家设计了壹套新的道具模型,指标是为了对Computer上的享有Linux统1配备进行统1地意味着和操作,包涵Linux统1道具本身和装置之间的连日关系。


 

这些模型是在条分缕析了 PCI 和 USB 的总线驱动进度中获得的,这四个总线类型能表示当前系统中的大繁多道具档案的次序,它们都有完善的热挺拔机制和电源处理的补助,也都有级连机制的帮助,以桥接的 PCI/USB 总线调节器的格局得以协助越多的 PCI/USB 设备。为了给全数设施加上统壹的电源管理的支撑,而不是让各样Linux统壹配备中去单独完结电源管理的支撑,大家思量的是哪些尽量地引用代码;而且在有档期的顺序模型的 PCI/USB 总线中,必须以合理情势体现出这几个档次关系,那也是电源管理等所供给的总得有档次结构。

Overview

Linux 二.陆根本的三个根本特点是提供了统1的木本设备模型。随着本领的不断升高,系统的拓扑结构特别复杂,对智能电源管理、热插拔以及plug and play的援救要求也更是高,二.四水源已经难以满意这么些须要。为适应这种时势的供给,2.陆内核开荒了全新的器材模型。

如在三个卓绝的 PC 系统中,中心管理器(CPU)能一向调控的是 PCI 总线设备,而 USB 总线设备是以多少个 PCI 设备(PCI-USB桥)的款型接入在 PCI 总线设备上,外部 USB 设备再接入在 USB 总线设备上;当Computer实行挂起(suspend)操作时, Linux 内核应该以 “外部USB设备->USB总线设备->PCI总线设备” 的相继通告每3个设施将电源挂起;施行复苏(resume)时则以相反的逐1公告;反之假使不按此顺序则将有器材得不到正确的电源状态变迁的文告,将不可能寻常职业。

设计指标

  • 电源管理和系统关机(Power management and system shutdown)

    设备之间大多情况下有依赖、耦合,因此要实现电源管理就必须对系统的设备结构有清楚的理解,应知道先关哪个然后才能再关哪个。设计设备模型就是为了使系统可以按照正确顺序进行硬件的遍历。
    
  • 与用户空间的互相(Communications with user space)

    实现了sysfs虚拟文件系统。它可以将设备模型中定义的设备属性信息等导出到用户空间,使得在用户空间可以实现对设备属性的访问及参数的更改。详见Documentation/filesystems/sysfs.txt。
    
  • 可热插拔设备(Hotpluggable devices)

    设备模型管理内核所使用的处理用户空间热插拔的机制,支持设备的动态添加与移除。
    
  • 设备项目(Device classes)

    系统的许多部分对设备如何连接没有兴趣, 但是它们需要知道什么类型的设备可用。设备模型也实现了一个给设备分类的机制, 它在一个更高的功能性级别描述了这些设备。
    
  • 对象生命期(Object lifecycles)

    设备模型的实现一套机制来处理对象生命期。
    

1. Sysfs文件系统

sysfs 是在这些 Linux统一器械模型的支出进程中的1项副产品(见 仿效资料 中 格雷戈 K. Hartman 写作的 LinuxJournal 小说)。为了将这几个有等级次序结构的配备以用户程序可知的方法表明出来,大家很当然想到了选用文件系统的目录树结构那是以 UNIX 格局思量难题的底子,壹切都以文件!)在那些模型中,有二种为主项目它们的相应关系。

设施模型框图

Linux 设备模型是一个叶影参差的数据结构。如图所示为和USB鼠标相关联的道具模型的一小部分:
亚洲城 1

其1框图展示了道具模型最关键的多个部分的协会关系(在顶层容器中详解):

  • Devices

    描述了设备如何连接到系统。
    
  • Drivers

    系统中可用的驱动。
    
  • Buses

    跟踪什么连接到每个总线,负责匹配设备与驱动。
    
  • classes

    设备底层细节的抽象,描述了设备所提供的功能。
    

Sysfs文件系统是贰个近似于proc文件系统的特种文件系统,用于将系统中的设备组织成档期的顺序结构,并向用户格局先后提供详实的木本数据结构新闻。其顶层目录重要有:

Linux统1配备模型的骨干协会

底层完成

Block目录:蕴涵全部的块设备

花色 所富含的开始和结果 对应内核数据结构 对应/sys项
装备(Devices) 设备是此模型中最中央的品种,以设备本人的连天按档期的顺序组织struct device /sys/devices/*/*/.../
设施驱动(Device Drivers) 在三个系统中设置多个相同设备,只要求1份驱动程序的支撑 struct device_driver /sys/bus/pci/drivers/*/
总线类型(Bus Types) 在全部总线品级对此总线上接连的全数设施实行管制 struct bus_type /sys/bus/*/
道具项目(Device Classes) 那是根据职能拓展分拣协会的设施档次树;如 USB 接口和 PS/二 接口的鼠标都以输入设备,都会油但是生在 /sys/class/input/ 下 struct class /sys/class/*/

kobject

Devices目录:包括系统全体的设施,并依靠设备挂接的总线类型组织成档案的次序结构

从根本在实现它们时所选用的数据结构来讲, Linux统1道具模型又是以两种基本数据结构进行树型和链表型结构协会的:
kobject: 在 Linux统壹器械模型中最基本的靶子,它的效益是提供引用计数和维持父亲和儿子(parent)结构、平级(sibling)目录关系,下面的 device, device_driver 等各目标都以以 kobject 基础功效之上实现的; struct kobject {
const char      *name;
struct list_headentry;
struct kobject  *parent;
struct kset     *kset;
struct kobj_type*ktype;
struct sysfs_dirent     *sd;
struct kref     kref;
unsigned int state_initialized:1;
unsigned int state_in_sysfs:1;
unsigned int state_add_uevent_sent:1;
unsigned int state_remove_uevent_sent:1;

职能与指标

Kobject是将全体设施模型连接在联合的底子。主要用以完结以下职能:

  • 目的的引用计数(Reference counting of objects)

    通常, 当一个内核对象被创建, 没有方法知道它会存在多长时间。 一种跟踪这种对象生命周期的方法是通过引用计数。 当没有内核代码持有对给定对象的引用, 那个对象已经完成了它的有用寿命并且可以被删除。
    
  • sysfs 表示(Sysfs representation)

    在sysfs中显示的每一个项目都是通过一个与内核交互的kobject实现的。
    
  • 数据结构粘和(Data structure glue)

    设备模型整体来看是一个极端复杂的由多级组成的数据结构, kobject实现各级之间的连接粘和。
    
  • 热插拔事件处理(Hotplug event handling)

    kobject处理热插拔事件并通知用户空间。
    

Bus目录:包涵系统中具备的总线类型

中间 struct kref 内含一个 atomic_t 类型用于引用计数, parent 是单个指向父节点的指针, entry 用于父 kset 以链表头结构将 kobject 结构维护成双向链表;
kset: 它用来对同类型对象提供一个封装集结,在基础数据结构上它也是由内嵌三个kboject 达成,由此它相同的时候也是二个 kobject (面向对象 OOP 概念中的承接关系) ,具备 kobject 的总体功能; struct kset {
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
struct kset_uevent_ops *uevent_ops;

数据结构

/* include in <linux/kobject.h> */

struct kobject {
    const char *name; /* 该kobject的名称,同时也是sysfs中的目录名称 */
    struct list_head entry; /* kobjetct双向链表 */
    struct kobject *parent; /* 指向kset中的kobject,相当于指向父目录 */
    struct kset *kset; /*指向所属的kset*/
    struct kobj_type *ktype; /*负责对kobject结构跟踪*/
    ...
};

/* 定义kobject的类型及释放回调 */
struct kobj_type {
    void (*release)(struct kobject *); /* kobject释放函数指针 */
    struct sysfs_ops *sysfs_ops; /* 默认属性操作方法 */
    struct attribute **default_attrs; /* 默认属性 */
};

/* kobject上层容器 */
struct kset {    
    struct list_head list; /* 用于连接kset中所有kobject的链表头 */
    spinlock_t list_lock; /* 扫描kobject组成的链表时使用的锁 */
    struct kobject kobj; /* 嵌入的kobject */
    const struct kset_uevent_ops *uevent_ops; /* kset的uevent操作 */
};

/* 包含kset的更高级抽象 */
struct subsystem {
    struct kset kset; /* 定义一个kset */
    struct rw_semaphore rwsem; /* 用于串行访问kset内部链表的读写信号量 */
};

kobject和kset关系:
亚洲城 2

如图所示,kset将它的children(kobjects)组成三个正经的根本链表。所以说kset是三个包罗嵌入在同体系型结构中的kobject的集聚。它本人也内嵌3个kobject,所以也是四个例外的kobject。设计kset的首要指标是兼容,能够说是kobject的顶层容器。kset总是会在sysfs中以目录的样式表现。供给小心的是图中所示的kobject其实是停放在别的品类中(非常的少单独使用),也只怕是别的kset中。

kset和subsystem关系:
三个子系列subsystem, 其实只是2个叠合了个读写时域信号量的kset的包装,反过来正是说每一个 kset 必须属于一个子系列。依据subsystem之间的成员涉及创立kset在全部层级中的地点。
子系统不常使用宏直接静态定义:

    /* 定义一个struct subsystem name_subsys 并初始化kset的type及hotplug_ops */
    decl_subsys(name, struct kobj_type *type,struct kset_hotplug_ops *hotplug_ops);

Drivers目录:包涵基本中颇具已注册的道具驱动程序

其中的 struct list_head list 用于将聚集中的 kobject 按 struct list_head entry 维护成双向链表;
涉及到文件系统实现的话, sysfs 是一种基于 ramfs 完结的内存文件系统,与任何相同以 ramfs 完毕的内部存款和储蓄器文件系统(configfs,debugfs,tmpfs,...)类似, sysfs 也是从来以 VFS 中的 struct inode 和 struct dentry 等 VFS 档案的次序的结构体直接完结文件系统中的各个对象;同期在各种文件系统的私有数据 (如 dentry->d_fsdata 等地方) 上,使用了名叫 struct sysfs_dirent 的结构用于表示 /sys 中的每1个索引项。
struct sysfs_dirent {
atomic_ts_count;
atomic_ts_active;
struct sysfs_dirent     *s_parent;
struct sysfs_dirent     *s_sibling;
const char      *s_name;
union {
struct sysfs_elem_dir   s_dir;
struct sysfs_elem_symlink       s_symlink;
struct sysfs_elem_attr  s_attr;
struct sysfs_elem_bin_attr      s_bin_attr;
unsigned int    s_flags;
ino_t   s_ino;
umode_t s_mode;
struct iattr    *s_iattr;

操作函数

  • 初始化
/* 初始化kobject内部结构 */
void kobject_init(struct kobject *kobj);
/* 设置name */
int kobject_set_name(struct kobject *kobj, const char *format, ...);

/* 先将kobj->kset指向要添加的kset中,然后调用会将kobject加入到指定的kset中 */
int kobject_add(struct kobject *kobj);
/* kobject_register = kobject_init   kobject_add */
extern int kobject_register(struct kobject *kobj);

/* 对应的Kobject删除函数 */
void kobject_del(struct kobject *kobj);
void kobject_unregister(struct kobject *kobj);

/* 与kobject类似的kset操作函数 */
void kset_init(struct kset *kset);
kobject_set_name(&my_set->kobj, "The name");
int kset_add(struct kset *kset);
int kset_register(struct kset *kset);
void kset_unregister(struct kset *kset);

Tip: 开头化前应先利用memset将kobj清零;起始化完毕后引用计数为一

  • 引用计数管理
/* 引用计数加1并返回指向kobject的指针 */
struct kobject *kobject_get(struct kobject *kobj);
/* 当一个引用被释放, 调用kobject_put递减引用计数,当引用为0时free这个object */
void kobject_put(struct kobject *kobj);

/* 与kobject类似的kset操作函数 */
struct kset *kset_get(struct kset *kset);
void kset_put(struct kset *kset);
  • 释放
当引用计数为0时,会调用ktype中的release,因此可以这样定义release回调函数:
void my_object_release(struct kobject *kobj)
{
    struct my_object *mine = container_of(kobj, struct my_object, kobj);
    /* Perform any additional cleanup on this object, then... */
    kfree(mine);
}

/* 查找ktype */
struct kobj_type *get_ktype(struct kobject *kobj);
  • subsystem相关
decl_subsys(name, type, hotplug_ops);
void subsystem_init(struct subsystem *subsys);
int subsystem_register(struct subsystem *subsys);
void subsystem_unregister(struct subsystem *subsys);
struct subsystem *subsys_get(struct subsystem *subsys);
void subsys_put(struct subsystem *subsys);

Class目录:系统中的设备项目(如网卡设备,声卡设备等)

在地点的 kobject 对象中得以看到有向 sysfs_dirent 的指针,由此在sysfs中是用同样种 struct sysfs_dirent 来Linux统1道具模型中的 kset/kobject/attr/attr_group.

Low-Level Sysfs Operations

二. 基本对象机制重视数据结构  www.贰cto.com  

具体在数据结构成员上, sysfs_dirent 上有一个 union 共用体包蕴二种分裂的构造,分别是目录、符号链接文件、属性文件、二进制属性文件;在那之中目录项目可以对应 kobject,在对应的 s_dir 中也许有对 kobject 的指针,因而在根本数据结构, kobject 与 sysfs_dirent 是互相引用的;

kobject和sysfs关系

kobject是达成sysfs虚拟文件系统背后的编写制定。sysfs中的每1个目录都对应内核中的3个kobject。将kobject的天性(atrributes)导出就能够在sysfs对应的目录下爆发由基本自动生成的包蕴那个属性新闻的文书。只需轻巧的调用前边所涉及的kobject_add就能够在sysfs中生成三个对应kobject的输入,但值得注意的是:

  • 以此进口总会以目录彰显, 也正是说生成1个入口正是成立一个目录。平时这些目录会包蕴2个或多少个属性文件(见下文)。
  • 分配给kobject的名字(用kobject_set_name)正是给 sysfs 目录使用的名字,因而在sysfs层级中一律部分的kobject命名必须唯一,不能够包蕴下划线,幸免采用空格。
  • 这么些进口所处的目录表示kobject的parent指针,借使parent为NULL,则针对的是它的kset,因而可以说sysfs的层级其实对应的正是kset的层级。但当kset也为NULL时,这一个进口就能够创设在sysfs的top level,然则事实上中异常少出现这种场地。

二.一 kobject内核查象

sysfs 所表明的 /sys 目录结构就是极度清晰明了:
在 /sys 根目录之下的都以 kset,它们组织了 /sys 的顶层目录视图;
在一些 kset 下有二级或更加深档次的 kset;
各种 kset 目录下再包括着2个或多个 kobject,这代表二个集结所包涵的 kobject 结构体;
在 kobject 下有属性(attrs)文件和属性组(attr_group),属性组就是集体属性的一个索引,它们一同向用户层提供了代表和操作那么些kobject 的本性特征的接口;
在 kobject 下还大概有局部标识链接文件,指向别的的 kobject,这几个标志链接文件用于集体地点所说的 device, driver, bus_type, class, module 之间的关系;
差异品类如设备项目标、设备驱动类型的 kobject 都有两样的性质,不一样驱动程序支持的 sysfs 接口也可能有例外的习性文件;而同样等级次序的配备上有多数一样的脾气文件;
留神,此表内容是鲁人持竿最新开辟中的 二.陆.28 内核的立异组织的,在附录财富如 LDD三 等义务中有关系 sysfs 中曾有一种管理对象称为 subsys (子系统对象),在风靡的根本中经过重构以为它是无需的,它的成效完全能够由 kset 取代,也便是说 sysfs 中只需求一种管理组织是 kset,一种表示切实对象的结构是 kobject,在 kobject 下再用属性文件表示那个指标所负有的品质。以上是介绍Linux统一器材。

属性(atrributes)

品质即为下面所关联的要是导出就能够由基础自动生成的带有kobject内核音信的文本。结构如下:

struct attribute {
    char *name; /* 属性名,也是sysfs对应entry下的文件名 */
    struct module *owner; /* 指向负责实现这个属性的模块 */
    mode_t mode; /* 权限位,在<linux/stat.h>中定义 */
};

属性的导出显示及导入存款和储蓄函数:

/* kobj: 需要处理的kobject
   attr: 需要处理的属性
   buffer: 存储编码后的属性信息,大小为PAGE_SIZE
   return: 实际编码的属性信息长度
   */
struct sysfs_ops {
    ssize_t (*show)(struct kobject *kobj, struct attribute *attr,char *buffer); /* 导出到用户空间 */
    ssize_t (*store)(struct kobject *kobj, struct attribute *attr,const char *buffer, size_t size); /* 存储进内核空间 */
};

急需专注的是:

  • 各样属性都是用name=value表示,name即便属性的公文名,value即文件内容,要是value超过PAGE_SIZE,则应分为几特天性来管理;
  • 上述函数能够管理分歧的属性。能够在里边贯彻时同过属性名举办区分来促成;
  • 出于store是从用户空间到根本,所以实现时首先要反省参数的法定行,避防内核崩溃及任何难题。

Kobject 是Linux 二.6引进的新的设备管理机制,在基础中由struct kobject表示。通过那么些数据结构使全部器具在尾部都独具合并的接口,kobject提供基本的靶子管理,是构成Linux 2.六道具模型的中央结构,它与sysfs文件系统紧凑关联,每种在基本中注册的kobject对象都对应于sysfs文件系统中的1个目录。

  1. 10大Linux操作系统要点
  2. Linux操作系统非你不可的说辞
  3. 阐释Linux操作系统安装与认知支援的硬体
  4. Linux操作系统对于Windows算怎么?
  5. 座谈测试Fedora Linux硬件使用功用
缺省属性(Default Attributes)

在kobject成立时都会赋予一些缺省的默许属性,即上边所提到的kobj_type中的default_attrs数组,这些数组的最后一个分子须安装成NULL,以表示数组大小。全部应用那些kobj_type的kobject都以经过kobj_type中的sfsfs_ops回调函数入口达成对缺省属性的定义。

Kobject结构定义为:

Linux 二.5 内核的成本进程...

非缺省属性(Nondefault Attributes)

相似的话,定义时就能够经过default_attrs实现成着的性质,但这里也提供了继续动态增进和删除属性的章程:

   int sysfs_create_file(struct kobject *kobj, struct attribute *attr);
   int sysfs_remove_file(struct kobject *kobj, struct attribute *attr);

struct kobject {

二进制属性(Binary Attributes)

上述性情包罗的可读的文本值,二进制属性非常少使用,繁多用在从用户空间传递一些不改换的文件如firmware给道具的情状下。

        struct bin_attribute {
            struct attribute attr; /* 定义name,owner,mode */
            size_t size; /* 属性最大长度,如没有最大长度则设为0 */
            ssize_t (*read)(struct kobject *kobj, char *buffer,loff_t pos, size_t size);
            ssize_t (*write)(struct kobject *kobj, char *buffer,loff_t pos, size_t size);
        };

read/write一回加载多次调用,每一遍最多PAGE_SIZE大小。注意write不能够指示最后3个写操作,得经过其余措施推断操作的达成。
贰进制属性不可能定义为缺省值,由此需明确的创导与删除:

        int sysfs_create_bin_file(struct kobject *kobj,struct bin_attribute *attr);
        int sysfs_remove_bin_file(struct kobject *kobj,struct bin_attribute *attr);

char * k_name;    指向设备名称的指针

标识连接(Symbolic Links)

方法:

    int sysfs_create_link(struct kobject *kobj, struct kobject *target,char *name);
    void sysfs_remove_link(struct kobject *kobj, char *name);

char name[KOBJ_NAME_LEN];   设备名称

热插拔事件生成(Hotplug 伊夫nt Generation)

热插拔事件即当系统布署产生改变是内核向用户空间的打招呼。然后用户空间会调用/sbin/hotplug通过创办节点、加载驱动等动作进行响应。那一个热插拔事件的发出是在kobject_add和kobject_del时。大家能够由此地方kset中定义的uevent_ops对热插拔事件时有发生进行布署:

struct kset_uevent_ops {
    /* 实现事件的过滤,其返回值为0时不产生事件 */
    int (* const filter)(struct kset *kset, struct kobject *kobj);
    /* 生成传递给/sbin/hotplug的name参数 */
    const char *(* const name)(struct kset *kset, struct kobject *kobj);
    /* 其他传递给/sbin/hotplug的参数通过这种设置环境变量的方式传递 */
    int (* const uevent)(struct kset *kset, struct kobject *kobj,
              struct kobj_uevent_env *env);
};

struct kref kref;    对象引用计数

顶层容器

struct list_head entry;   挂接到所在kset中去的单元

Buses, Devices, Drivers and Classes

struct kobject * parent; 指向父对象的指针

Buses

总线Buses是计算机和设施的锦绣前程。在设备模型中,全部设备都以透过总线连接在协同的,哪怕是贰个里头虚拟的platform总线。

/* defined in  <linux/device.h> */

struct bus_type {    
    const char *name; /* 总线类型名 */    
    struct bus_attribute *bus_attrs; /* 总线的属性 */    
    struct device_attribute *dev_attrs; /* 设备属性,为每个加入总线的设备建立属性链表 */    
    struct driver_attribute *drv_attrs; /* 驱动属性,为每个加入总线的驱动建立属性链表 */

    /* 驱动与设备匹配函数:当一个新设备或者驱动被添加到这个总线时,
       这个方法会被调用一次或多次,若指定的驱动程序能够处理指定的设备,则返回非零值。
       必须在总线层使用这个函数, 因为那里存在正确的逻辑,核心内核不知道如何为每个总线类型匹配设备和驱动程序 */    
    int (*match)(struct device *dev, struct device_driver *drv); 

    /*在为用户空间产生热插拔事件之前,这个方法允许总线添加环境变量(参数和 kset 的uevent方法相同)*/    
    int (*uevent)(struct device *dev, struct kobj_uevent_env *env);    
    ...

    struct subsys_private *p; /* 一个很重要的域,包含了device链表和drivers链表 */
}

/* 定义bus_attrs的快捷方式 */
BUS_ATTR(name, mode, show, store);

/* bus属性文件的创建移除 */
int bus_create_file(struct bus_type *bus, struct bus_attribute *attr);
void bus_remove_file(struct bus_type *bus, struct bus_attribute *attr);

/* 总线注册 */
int bus_register(struct bus_type *bus);
void bus_unregister(struct bus_type *bus);

/* 遍历总线上的设备与驱动 */
int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data, int(*fn)(struct device *, void *));
int bus_for_each_drv(struct bus_type *bus, struct device_driver *start, void *data, int(*fn)(struct device_driver *, void *));

struct kset * kset;    所属kset的指针

Devices

Linux中,每2个平底设备都以structure device的2个实例:

struct device {
     struct device *parent; /* 父设备,总线设备指定为NULL */    
     struct device_private *p; /* 包含设备链表,driver_data(驱动程序要使用数据)等信息 */    
     struct kobject kobj;    
     const char *init_name; /* 初始默认的设备名 */
     struct bus_type *bus; /* type of bus device is on */    
     struct device_driver *driver; /* which driver has allocated this device */
     ...
     void (*release)(struct device *dev); 
};

int device_register(struct device *dev);
void device_unregister(struct device *dev);

DEVICE_ATTR(name, mode, show, store);
int device_create_file(struct device *device,struct device_attribute *entry);
void device_remove_file(struct device *dev,struct device_attribute *attr);

struct kobj_type * ktype;   指向其目的类型描述符的指针

Drivers

设备模型追踪全部系统已知的驱动。

struct device_driver {    
    const char *name; /* 驱动名称,在sysfs中以文件夹名出现 */    
    struct bus_type *bus; /* 驱动关联的总线类型 */    
    int (*probe) (struct device *dev); /* 查询设备的存在 */
    int (*remove) (struct device *dev); /* 设备移除回调 */   
    void (*shutdown) (struct device *dev);
    ...
}

int driver_register(struct device_driver *drv);
void driver_unregister(struct device_driver *drv);

DRIVER_ATTR(name, mode, show, store);
int driver_create_file(struct device_driver *drv,struct driver_attribute *attr);
void driver_remove_file(struct device_driver *drv,struct driver_attribute *attr);

struct dentry * dentry; sysfs文件系统中与该对象对应的文件节点路线指针

Classes

类是器械的贰个高档视图,完结了尾巴部分细节。通过对配备开始展览分拣,同类代码可共享,减少了根本代码的冗余。

struct class {
    const char      *name; /* class的名称,会在“/sys/class/”目录下体现 */

    struct class_attribute      *class_attrs;
    struct device_attribute     *dev_attrs; /* 该class下每个设备的attribute */
    struct kobject          *dev_kobj;

    /* 当该class下有设备发生变化时,会调用class的uevent回调函数 */
    int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
    char *(*devnode)(struct device *dev, mode_t *mode);

    void (*class_release)(struct class *class);
    void (*dev_release)(struct device *dev);

    int (*suspend)(struct device *dev, pm_message_t state);
    int (*resume)(struct device *dev);

    struct class_private *p;
};

int class_register(struct class *cls);
void class_unregister(struct class *cls);

CLASS_ATTR(name, mode, show, store);
int class_create_file(struct class *cls,const struct class_attribute *attr);
void class_remove_file(struct class *cls,const struct class_attribute *attr);

};

Putting It All Together

亚洲城 3

本文永恒更新链接地址:http://www.linuxidc.com/Linux/2016-12/138151.htm

亚洲城 4

中间的kref域表示该目的引用的计数,内核通过kref完结指标引用计数管理,内核提供八个函数kobject_get()、kobject_put()分别用于扩大和压缩引用计数,当引用计数为0时,全部该对象使用的资源将被保释。

Ktype 域是贰个对准kobj_type结构的指针,表示该目的的花色。Kobj_type数据结构包括多少个域:3个release方法用于释放kobject占 用的能源;2个sysfs_ops指针指向sysfs操作表和三个sysfs文件系统缺省属性列表。Sysfs操作表包涵三个函数store()和 show()。当用户态读取属性时,show()函数被调用,该函数编码钦命属性值存入buffer中回到给用户态;而store()函数用于存款和储蓄用户态传入的属性值。

二.贰 kset内核对象集结

Kobject平常经过kset组织成档次化的组织,kset是具有同等类其余kobject的集结,在根本中用kset数据结构表示,定义为:

struct kset {

struct subsystem * subsys;   所在的subsystem的指针

struct kobj_type * ktype;   指向该kset对象类型描述符的指针

struct list_head list;      用于连接该kset中颇具kobject的链表头

struct kobject kobj;     嵌入的kobject

struct kset_hotplug_ops * hotplug_ops; 指向热插拔操作表的指针

};

含有在kset中的全数kobject被组织成2个双向循环链表,list域正是该链表的头。Ktype域指向2个kobj_type结构,被该 kset中的全部kobject共享,表示那么些目的的系列。Kset数据结构还内嵌了三个kobject对象(由kobj域表示),全数属于那一个kset 的kobject对象的parent域均指向那么些内嵌的目标。别的,kset还依据于kobj维护引用计数:kset的引用计数实际上正是内嵌的 kobject对象的引用计数。

二.三 subsystem内查对象子系统

Subsystem是壹多级kset的会合,描述系统中某1类设备子系统,如block_subsys表示具备的块设备,对应于sysfs文件系统中的block目录。类似的,devices_subsys对应于 sysfs中的devices目录,描述系统中具有的设施。Subsystem由struct subsystem数据结构描述,定义为:

struct subsystem {

struct kset kset;       内嵌的kset对象

struct rw_semaphore rwsem; 互斥访问随机信号量

};

每个kset必须属于某些subsystem,通过设置kset结构中的subsys域指向钦定的subsystem能够将3个kset参加到该 subsystem。全体挂接到同一subsystem的kset共享同一个rwsem时限信号量,用于共同访问kset中的链表。

 

三. 水源对象机制重大相关函数

针对内核对象不一致档次的数据结构,linux 贰.陆内核定义了壹比比皆是操作函数,定义于lib/kobject.c文件中。  www.贰cto.com  

3.一 kobject相关函数

void kobject_init(struct kobject * kobj);

kobject初叶化函数。设置kobject引用计数为一,entry域指向自个儿,其所属kset引用计数加壹。

int kobject_set_name(struct kobject *kobj, const char *format, ...);

安装钦定kobject的名目。

void kobject_cleanup(struct kobject * kobj)和void kobject_release(struct kref *kref);

kobject清除函数。当其引述计数为0时,释放对象占用的财富。

struct kobject *kobject_get(struct kobject *kobj);

将kobj 对象的引用计数加壹,同时重回该指标的指针。

void kobject_put(struct kobject * kobj);

将kobj对象的引用计数减一,假若引用计数降为0,则调用kobject_release()释放该kobject对象。

int kobject_add(struct kobject * kobj);

将kobj对象参加Linux设备等级次序。挂接该kobject对象到kset的list链中,扩张父目录各级kobject的引用计数,在其parent指向的目录下创制文件节点,并运营该类型内核查象的hotplug函数。

int kobject_register(struct kobject * kobj);

kobject注册函数。通过调用kobject_init()初始化kobj,再调用kobject_add()达成该内核查象的挂号。

void kobject_del(struct kobject * kobj);

从Linux设备档次(hierarchy)中剔除kobj对象。

void kobject_unregister(struct kobject * kobj);

kobject注销函数。与kobject_register()相反,它首先调用kobject_del从设备档次中除去该对象,再调用kobject_put()缩小该指标的引用计数,假若引用计数降为0,则释放该kobject对象。

三.二 kset相关函数

与kobject 相似,kset_init()完结钦命kset的开始化,kset_get()和kset_put()分别大增和收缩kset对象的引用计数。 Kset_add()和kset_del()函数分别完成将钦赐keset对象加入设备档次和从里头删除;kset_register()函数完毕kset的挂号而kset_unregister()函数则成功kset的撤销。

叁.3 subsystem相关函数

subsystem有1组完毕临近的函数,分别是:

void subsystem_init(struct subsystem *subsys);

int subsystem_register(struct subsystem *subsys);

void subsystem_亚洲城,unregister(struct subsystem *subsys);

struct subsystem *subsys_get(struct subsystem *subsys)

void subsys_put(struct subsystem *subsys);

四. 配备模型组件

在上述内查对象机制的基础上,Linux的设备模型构建在多少个关键组件的根基上,上面大家详细阐释那几个组件。

4.1 devices

系统中的任一设备在装置模型中都由二个device对象描述,其相应的数据结构struct device定义为:

struct device {

struct list_head g_list; 

struct list_head node;

    struct list_head bus_list;

    struct list_head driver_list;

    struct list_head children;

    struct device *parent;

    struct kobject kobj;

    char bus_id[BUS_ID_SIZE];

    struct bus_type *bus;

    struct device_driver *driver;

    void *driver_data;

    /* Several fields omitted */

};

g_list 将该device对象挂接到全局设备链表中,全体的device对象都包涵在devices_subsys中,并集体成等级次序结构。Node域将该对象挂接 到其兄弟对象的链表中,而bus_list则用来将一连到平等总线上的设施组织成链表,driver_list则将一仍其旧驱动程序管理的兼具设施协会为链 表。别的,children域指向该device对象子对象链表头,parent域则指向父对象。Device对象还内嵌三个kobject对象,用于引 用计数处理并透过它完结设备档期的顺序结构。Driver域指向管理该设施的驱动程序对象,而driver_data则是提需求驱动程序的多少。Bus域描述设 备所连接的总线类型。

基础提供了对应的函数用于操作device对象。在那之中Device_register()函数将贰个新的device对象插 入设备模型,并自动在/sys/devices下创办贰个相应的目录。Device_unregister()完毕相反的操作,注销设备对象。 Get_device()和put_device()分别大增与减弱设备对象的引用计数。经常device结构不独立行使,而是含有在越来越大的组织中作为一身长结构选拔,举个例子描述PCI设备的struct pci_dev,个中的dev域正是1个device对象。  www.贰cto.com  

4.2 drivers

系统中的每一种驱动程序由二个device_driver对象描述,对应的数据结构定义为:

struct device_driver {

    char *name;   设备驱动程序的名号

    struct bus_type *bus; 该驱动所管理的设备挂接的总线类型

    struct kobject kobj;    内嵌kobject对象

    struct list_head devices;   该驱动所管理的器具链表头

    int (*probe)(struct device *dev); 指向设备探测函数,用于探测器具是或不是足以被该驱动程序管理

int (*remove)(struct device *dev); 用于删除设备的函数

/* some fields omitted*/

};

与device 结构类似,device_driver对象依据内嵌的kobject对象完结引用计数处理和档次结构组织。内核提供类似的函数用于操作 device_driver对象,如get_driver()扩大引用计数,driver_register()用于向设备模型插入新的driver对 象,同不时候在sysfs文件系统中成立对应的目录。Device_driver()结构还包蕴多少个函数,用于拍卖热拔插、即插即用和电源处总管件。

4.3   buses

系统中总线由struct bus_type描述,定义为:

struct bus_type { 

char   * name; 总线类型的名称

struct subsystem subsys; 与该总线相关的subsystem

struct kset drivers; 全部与该总线相关的驱动程序群集

struct kset devices; 所有挂接在该总线上的装置会集

struct bus_attribute * bus_attrs; 总线属性

struct device_attribute * dev_attrs; 设备属性

struct driver_attribute * drv_attrs;   驱动程序属性

int (*match)(struct device * dev, struct device_driver * drv);

int (*hotplug) (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); 

int (*suspend)(struct device * dev, u32 state);

int (*resume)(struct device * dev);

};

每个bus_type对象都内嵌1个subsystem对象,bus_subsys对象处理系列中颇具总线类型的subsystem对象。每个bus_type对象都对应/sys/bus目录下的二个子目录,如PCI总线类型对应于/sys/bus/pci。在种种那样的目录下都存在八个子目 录:devices和drivers(分别对应于bus_type结构中的devices和drivers域)。当中devices子目录描述连接在该总 线上的具有设备,而drivers目录则讲述与该总线关联的持有驱动程序。与device_driver对象类似,bus_type结构还包涵多少个函数 (match()、hotplug()等)处理相应的热插拔、即插即拔和电源处监护人件。

4.4 classes

系统中的设备类由 struct class描述,表示某一类设备。全体的class对象都属于class_subsys子系统,对应于sysfs文件系统中的/sys/class目录。 每一种class对象包含贰个class_device链表,每个class_device对象表示三个逻辑设备,并经过struct class_device中的dev域(一个针对struct device的指针)关联贰个大要设备。那样,叁个逻辑设备总是对应于多个大意设备,可是2个物理设备却或然对应于几个逻辑设备。其它,class结构中 还包含用于拍卖热插拔、即插即拔和电源处监护人件的函数,那与device对象和driver对象一般。

 

device model

device model首要的数据结构有多个: kobject, kset 和 subsystem.

 

有关数据结构:

struct kobject {

 char   * k_name;

 char   name[KOBJ_NAME_LEN];

 struct kref  kref;

 struct list_head entry;

 struct kobject  * parent;

 struct kset  * kset;

 struct kobj_type * ktype;

 struct dentry  * dentry;

};

 

struct kset {

 struct subsystem * subsys;

 struct kobj_type * ktype;

 struct list_head list;

 spinlock_t  list_lock;

 struct kobject  kobj;

 struct kset_hotplug_ops * hotplug_ops;

};

   www.2cto.com  

struct subsystem {

 struct kset  kset;

 struct rw_semaphore rwsem;

};

 

他们是整个device model的龙骨(用面向对象的语气说:那叫基类(不是鸡肋^_`))。

任何全部的构造,例如cdev,bus等等,都是在这么些骨架上搭建起来的。

kobject是最最基础的。许多构造都会有1个内嵌的kobject.

kobject的引用计数功效是最首要的。

 

kset可以作为是1类kojbect的集结,而subsystem可以看成是多少kset的联谊。

 

多少个kset能够因此subsys指针指向3个subsystem。但subsystem仅蕴涵一个内嵌的kset。

这种单向关系表示不大概可是经过八个subsystem结构体就找到该subsystem全数的ksets。

他俩的牵连暗意图如下:

                                                        

                                                        

  /----------------------------->     kset     <----------------------------/

  |                               ------------                             |

  |                              |   subsys   |                             |

  |                               ------------                             |

  |                              |   ktype    |                             |

  |                               ------------                             |

  |   /------------------------->|   list     |<------------------------/   |

  |   |                           ------------                         |   |

  |   |                    /---->|   kobj     |<---/                    |   |

  |   |                    |     ------------    |                    |   |

  |   |                    |     | hotplug_ops|    |                    |   |

  |   |                    |     ------------    |                    |   |

  |   |                    |                       |                    |   |

  |   |                    |                       |                    |   |

  |   |                    |                       |                    |   |

  |   |                    |                       |                    |   |

  |   |                    |                       |                    |   |

  |   |                    |                       |                    |   |

  |   |                    |                       |                    |   |

  |   |       kobject      |                       |       kobject      |   |

  |   |     --------     |                       |     --------     |   |

  |   |     |        |     |                       |     |        |     |   |

  |   |     --------     |                       |     --------     |   |

  |   |     | parent |-----/                       /-----| parent |     |   |

  |   |     --------                                   --------     |   |

  |   /---->| entry  |<--------------------------------->| entry  |-----/   |

  |         --------                                   --------         |

  |         |        |                                   |        |         |

  |         --------                                   --------         |

  /---------| kset   |                                   | kset   |---------/

            --------                                   --------  

            |        |                                   |        |  

            --------                                   --------  

           

 

其余索要证实的是,kset中的list是贯通全数kobject的双向链表,但是并不一定是因而kobject的entry字段穿在协同的。

负有的kobject并不简单的是2个独自的kobject,而大概是内嵌在别的数据结构中的kobject(举个例子kset,subsystem 等等)

           

           

                                subsystem       <-----/  

                        ------------------------     | 

                       |             kset       |     | 

                       |         ------------- |     | 

                       |        |   subsys    |-------/ 

                       |         ------------- |      

                       |        |   ktype     | |

                       |  kset   ------------- |

                       |        |   list      | |

                       |         ------------- |

                       |        |   kobj      | |

                       |         ------------- |

                       |        | hotplug_ops | |  www.2cto.com  

                       |         ------------- |   

                       |------------------------|   

                       |                        |   

                       |      rwsem             |   

                       |                        |   

                        ------------------------   

                

                

装有的kset一定属于一个subsystem中(kset的subsys指向某3个subsystem)

对此subsystem内嵌的kset,假设未有设定它的subsys, 则是指向笔者的subsystem。(见subsystem_register()函数)

 

 

作者 Tommy_wxie

Linux 二.六基础的四个重视特色是提供了合并的木本设备模型。随着技巧的不断进步,系统的拓扑结构进一步复杂,对智能电...

编辑:亚洲城 本文来源:linux设备模型详解,归纳介绍Linux统1器械为主组织

关键词: 亚洲城ca88