Linux统一设备模型之我见

Linux设备模型为内核建立起一个统一的设备模型,从而有一个对系统结构的一般性抽象描述。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
______ _______ _________ _______ _______
( __ \ ( ____ \|\ /|\__ __/( ____ \( ____ \
| ( \ )| ( \/| ) ( | ) ( | ( \/| ( \/
| | ) || (__ | | | | | | | | | (__
| | | || __) ( ( ) ) | | | | | __)
| | ) || ( \ \_/ / | | | | | (
| (__/ )| (____/\ \ / ___) (___| (____/\| (____/\
(______/ (_______/ \_/ \_______/(_______/(_______/
_______ _______ ______ _______ _
( )( ___ )( __ \ ( ____ \( \
| () () || ( ) || ( \ )| ( \/| (
| || || || | | || | ) || (__ | |
| |(_)| || | | || | | || __) | |
| | | || | | || | ) || ( | |
| ) ( || (___) || (__/ )| (____/\| (____/\
|/ \|(_______)(______/ (_______/(_______/

1.背景

在 Linux 2.5 内核的开发过程中,人们设计了一套新的设备模型,目的是为了对计算机上的所有设备进行统一地表示和操作,包括设备本身和设备之间的连接关系。这个模型是在分析了 PCI 和 USB 的总线驱动过程中得到的,这两个总线类型能代表当前系统中的大多数设备类型,它们都有完善的热挺拔机制和电源管理的支持,也都有级连机制的支持,以桥接的 PCI/USB 总线控制器的方式可以支持更多的 PCI/USB 设备。为了给所有设备添加统一的电源管理的支持,而不是让每个设备中去独立实现电源管理的支持,人们考虑的是如何尽可能地重用代码;而且在有层次模型的 PCI/USB 总线中,必须以合理形式展示出这个层次关系,这也是电源管理等所要求的必须有层次结构。

如在一个典型的 PC 系统中,中央处理器(CPU)能直接控制的是 PCI 总线设备,而 USB 总线设备是以一个 PCI 设备(PCI-USB桥)的形式接入在 PCI 总线设备上,外部 USB 设备再接入在 USB 总线设备上;当计算机执行挂起(suspend)操作时, Linux 内核应该以 “外部USB设备->USB总线设备->PCI总线设备” 的顺序通知每一个设备将电源挂起;执行恢复(resume)时则以相反的顺序通知;反之如果不按此顺序则将有设备得不到正确的电源状态变迁的通知,将无法正常工作。

2.Linux统一设备模型

2.1 基本结构

类型 所包含的内容 对应的内核数据结构
设备(Device) 设备是此模型中最基本的类型,以设备本身的连接按层次组织 struct device
设备驱动(Device Drivver) 在一个系统中安装多个相同设备,只需要一份驱动程序的支持 struct device_driver
总线类型(Bus Types) 在整个总线级别对此总线上连接的所有设备进行管理 struct bus_type
设备类别(Device Classes) 按照功能进行分类组织的设备层次树,如键盘在输入类下 struct class

2.1 基本连接

从内核在实现它们时所使用的数据结构来说, Linux 统一设备模型又是以两种基本数据结构进行树型和链表型结构组织的:

  • kobject: 在 Linux 设备模型中最基本的对象,它的功能是提供引用计数和维持父子(parent)结构、平级(sibling)目录关系,上面的 device, device_driver 等各对象都是以 kobject 基础功能之上实现的。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    struct kobject {
    const char *name;
    struct list_head entry;
    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;
    };

其中 struct kref 内含一个 atomic_t 类型用于引用计数, parent 是单个指向父节点的指针, entry 用于父 kset 以链表头结构将 kobject 结构维护成双向链表;

  • kset: 它用来对同类型对象提供一个包装集合,在内核数据结构上它也是由内嵌一个 kboject 实现,因而它同时也是一个 kobject (面向对象 OOP 概念中的继承关系) ,具有 kobject 的全部功能。
    1
    2
    3
    4
    5
    6
    truct kset {
    struct list_head list;
    spinlock_t list_lock;
    struct kobject kobj;
    struct kset_uevent_ops *uevent_ops;
    };

其中的 struct list_head list 用于将集合中的 kobject 按 struct list_head entry 维护成双向链表。

版权声明:本文为博主原创文章,转载需声明为转载内容并添加原文地址。

原文地址:http://coderdock.com

Dock wechat
欢迎您扫一扫上面的微信公众号,订阅我的公众号