Linux设备模型
一、sysfs文件系统:
sysfs文件系统是Linux2.6内核引入的,它被看成是与proc、devfs和devpty等同类别的文件系统,sysfs文件系统也是一个虚拟文件系统,它可以产生一个包括所有系统硬件的层级视图,与提供进程和状态信息的proc文件系统十分类似;
sysfs文件系统把链接在系统上的所有设备和总线组织成一个分级的文件系统,它们可以由用户空间存取,并向用户空间导出内核数据结构以及它们的属性等信息.sysfs的一个目的就是展示设备驱动模型中各个组件的层次关系,其顶级目录包括:
1、block:包含系统中所有的块设备;
2、devices:包含系统中所有的设备,并根据设备挂载的总线类型组织成层次关系结构;
3、bus:包含系统中所有的总线类型;
4、drivers:包含系统内核中所有已经注册的设备驱动程序;
5、class:包含系统中所有的设备类型;如,网卡设备、声卡设备、输入设备、输出设备,等等;
二、设备模型:
从整体上描述,大概模型就如下图所示:
从图中可以看出,Linux设备模型就是"总线、设备、驱动、类"这四个概念之前的相互关系;这也是Linux2.6内核抽象出来的用于管理系统中所有设备的模型图;
简单地描述设备模型的层次关系如下:
1、驱动核心中可以注册多种类型的总线(bus_type);
2、每一种类型的总线下面可以挂载许多设备(kset,device);
3、每一种类型的总线可以使用很多设备驱动(kset,device_driver);
4、每一个驱动程序可以管理一组设备;
这种基本关系的建立源于实际系统中各种总线、设备、驱动、类结构的抽象;
Linux设备模型中的总线、设备、驱动和类之间环环相扣的复杂关系可以满足内核日益发展的的需要;对智能电源管理、热插拔以及即插即用的支持要求也越来越高;
三、实现:
Linux2.6设备模型框架由sysfs文件系统、udev和内核对象结构kobject、kset、subsystem、bus_type、device、device_driver、class、class_device、class_interface等重量级数据结构共同组成;这些统称为Linux设备模型组件;
设备类一、定义:
系统中的设备所属的类有结构体struct class对象来描述,用于表示某一类设备,它是一组具有共同属性和功能的设备的抽象体,类似于面向对象中的类的概念;所有的class对象都属于class_subsys子系统,对应于/sys/class目录;其结构定义如下:
struct class
{
const char* name; //类名
struct module* owner; //所属模块
struct subsystem subsys; //所属子系统subsystem
struct list_head children; //属于该class类型的所有子类组成的链表;
struct list_head devices; //属于该class类型的所有设备class_device组成的链表;
struct list_head interfaces; //类接口class_interface链表
struct semaphore sem; /* locks both the children and interfaces lists */
struct class_attribute* class_attrs; //类属性
struct class_device_attribute* class_dev_attrs; //类设备属性
int (*uevent)(struct class_device* dev, char** envp, int num_envp, char* buffer, int buffer_size);
void (*release)(struct class_device* dev);
void (*class_release)(struct class* class);
};
int class_register(struct class *cls):类注册;
void class_unregister(struct class *cls):类注销;
二、设备类属性:
struct class_attribute
{
struct attribute attr;
ssize_t (*show)(struct class* cls, char* buf);
ssize_t (*store)(struct class*, const char* buf, size_t count);
};
int class_create_file(struct class* cls, const struct class_attribute* attr):为指定设备类增加指定属性;
void class_remove_file(struct class* cls, const struct class_attribute* attr):删除指定设备类上的指定属性;
备注:struct class、struct class_attribute结构均定义在include/linux/device.h文件中;
类设备
一、定义:
一个设备类struct class的真正目的是作为一个该类具体实例(设备)的容器使用;一个设备类的具体实例由struct class_device结构来描述;也可以这样理解:struct class类型相当于面向对象系统中的类的概念,而struct class_device类型相当于面向对象系统中的实例对象的概念;只有在应用具体实例对象的时候,它的类才有意义;类设备struct class_device结构定义如下:
struct class_device
{
struct list_head node;
struct kobject kobj; //内嵌的kobject对象
struct class* class; //所属的设备类class
dev_t devt; //设备编号
struct class_device_attribute* devt_attr; //类设备属性
struct class_device_attribute uevent_attr; //类设备事件属性
struct device* dev; //如果存在,则创建到/sys/devices目录下相应入口的符号链接
void* class_data; //类私有数据
struct class_device* parent; //父设备,即,当前设备所附着到的设备
struct attribute_group** groups; /* optional groups */
void (*release)(struct class_device* dev);
int (*uevent)(struct class_device* dev, char** envp, int num_envp, char* buffer, int buffer_size);
char class_id[BUS_ID_SIZE]; //类唯一标识
};
二、类设备相关函数
int class_device_register(struct class_device* cd):类设备注册;
void class_device_unregister(struct class_device* cd):类设备注销;
int class_device_rename(struct class_device* cd, char* new_name):类设备重命名;
void class_device_initialize(struct class_device* cd):类设备初始化;
int class_device_add(struct class_device* cd):把类设备对象加入到设备模型的层次结构中;
void class_device_del(struct class_device* cd):把类设备对象从设备模型的层次结构中删除;
struct class_device * class_device_get(struct class_device* cd):给类设备对象增加引用计数;
void class_device_put(struct class_device* cd):给类设备对象减少引用计数;
备注:每一个设备类class对象都包含一个类设备class_device对象的链表,而每一个类设备class_device对象又表示一个逻辑设备,并通过类设备struct class_device结构中的dev成员(一个指向struce device的指针)关联到一个物理设备上;这样,一个逻辑设备总是对应于一个物理设备,但是,一个物理设备却可能对应多个逻辑设备;
三、类设备属性:
struct class_device_attribute
{
struct attribute attr;
ssize_t (*show)(struct class_device* cls, char* buf);
ssize_t (*store)(struct class_device* cls, const char* buf, size_t count);
};
int class_device_create_file(struct class_device* cd, const struct class_device_attribute* attr):为指定类设备增加指定属性;
void class_device_remove_file(struct class_device* cd, const struct class_device_attribute* attr):删除指定类设备上的指定属性;
int class_device_create_bin_file(struct class_device* cd, struct bin_attribute* attr);
void class_device_remove_bin_file(struct class_device* cd, struct bin_attribute* attr);
四、类接口:
当设备加入或离开类时,将引发class_interface中的成员函数被调用;
struct class_interface
{
struct list_head node;
struct class* class; //对应的设备类class
int (*add)(struct class_device* cd, struct class_interface* ci); //设备加入时触发
void (*remove)(struct class_device* cd, struct class_interface* ci); //设备移除时触发
};
int class_interface_register(struct class_interface* ci):类接口注册;
void class_interface_unregister(struct class_interface* ci):类接口注销;
struct class* class_create(struct module* owner, char* name):创建类;
void class_destroy(struct class* cls):销毁类;
//创建类设备
struct class_device *class_device_create(struct class *cls, struct class_device *parent, dev_t devt, struct device *device, char *fmt, ...);
//销毁类设备
void class_device_destroy(struct class *cls, dev_t devt);
备注:struct class_device、struct class_device_attribute、struct class_interface结构均定义在include/linux/device.h文件中;
Linux内核对象---subsystem
一、subsystem定义:
subsystem是一系列kset的集合,它用于描述系统中某一类设备子系统;例如,block_subsys表示所有的块设备,对应于sysfs文件系统中的block目录,而devices_subsys用于描述系统中所有的设备,对应于sysfs文件系统中的devices目录;subsystem结构定义如下:
struct subsystem
{
struct kset kset; //内嵌的kset对象
struct rw_semaphore rwsem; //用于互斥访问的信号量
};
每个kset对象必须隶属于某一个subsystem对象,通过设置kset对象结构中的subsys字段,使之指向指定的subsystem对象,这样就可以把一个kset对象加入到这个指定的subsystem对象中;所有挂接在同一个subsystem对象上的kset对象共享同一个rwsem信号量,用于同步访问kset对象中的链表;
二、subsystem相关函数:
1、void subsystem_init(struct subsystem *subsys):初始化subsystem对象;
2、int subsystem_register(struct subsystem *subsys):注册subsystem对象;
3、void subsystem_unregister(struct subsystem *subsys)注销subsystem对象;
4、struct subsystem *subsys_get(struct subsystem *subsys):把subsystem对象的引用计数加1;
5、void subsys_put(struct subsystem *subsys):把subsystem对象的引用计数减1;
备注:struct subsystem结构定义于文件include/linux/kobject.h