携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情
linux设备驱动模型
为什么需要设备驱动模型
- 早期内核(2.4之前)没有统一的设备驱动模型,但照样可以用
- 2.4~2.6期间使用devfs,挂载在/dev目录。
- 需要在内核驱动中创建设备文件(devfs_register),命名死板
- 2.6以后使用sysfs,挂载在/sys目录
- 将设备分类、分层次统一进行管理
- 配合udev/mdev守护进程动态创建设备文件,命令规则自由制定
sysfs概述
linux系统通过sysfs体现出设备驱动模型
- sysfs是一个虚拟文件系统(类似proc文件系统)
- 目录对应的inode节点会记录基本驱动对象(kobject),从而将系统中的设备组成层次结构
- 用户可以读写目录下的不同文件来配置驱动对象(kobject)的不同属性
设备驱动模型基本元素
-
kobject:sysfs中的一个目录,常用来表示基本驱动对象,不允许发送消息到用户空间
-
kset:sysfs中的一个目录,常用来管理kobject,允许发送消息到用户空间
-
kobj_type:目录下属性文件的操作接口
驱动模型一
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9tkvjSMP-1633618969932)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20200810194908453.png)]
kset可批量管理kobject
kobject无法批量管理kobject
驱动模型二
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5YRnHQkk-1633618969933)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20200810195127363.png)]
- 上层kobject节点无法遍历查找下层kobject
kobject
sysfs中每一个目录都对应一个kobject
include/linux/kobject.h
struct kobject {
//用来表示该kobject的名称
const char *name;
//链表节点
struct list_head entry;
//该kobject的上层节点,构建kobject之间的层次关系
struct kobject *parent;
//该kobject所属的kset对象,用于批量管理kobject对象
struct kset *kset;
//该Kobject的sysfs文件系统相关的操作和属性
struct kobj_type *ktype;
//该kobject在sysfs文件系统中对应目录项
struct kernfs_node *sd; /* sysfs directory entry */
//该kobject的引用次数
struct kref kref;
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
struct delayed_work release;
#endif
//记录内核对象的初始化状态
unsigned int state_initialized:1;
//表示该kobject所代表的内核对象有没有在sysfs建立目录
unsigned int state_in_sysfs:1;
unsigned int state_add_uevent_sent:1;
unsigned int state_remove_uevent_sent:1;
unsigned int uevent_suppress:1;
};
kset
struct kset {
//用来将起中的object对象构建成链表
struct list_head list;
//自旋锁
spinlock_t list_lock;
//当前kset内核对象的kobject变量
struct kobject kobj;
//定义了一组函数指针,当kset中的某些kobject对象发生状态变化需要通知用户空间时,调用其中的函数来完成
const struct kset_uevent_ops *uevent_ops;
}
kobj_type
struct kobj_type {
//销毁kobject对象时调用
void (*release)(struct kobject *kobj);
//kobject对象属性文件统一操作接口
const struct sysfs_ops *sysfs_ops;
//kobject默认属性文件的名字、"文件具体操作接口"
struct attribute **default_attrs;
const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
const void *(*namespace)(struct kobject *kobj);
void (*get_ownership)(struct kobject *kobj, kuid_t *uid, kgid_t *gid);
};