目录
一、为什么需要设备驱动模型
二、sysfs概述
驱动模型一
驱动模型二
kobject
kset
kobj_type
一、为什么需要设备驱动模型
- 早期内核(2.4之前)没有统一的设备驱动模型,但是照样可以使用(之前的led字符设备驱动),比较麻烦;
- 2.4~2.6期间使用devfs,挂载在/dev目录(需要在内核驱动中创建设备文件(devfs_register),命名死板);
- 2.6以后使用sysfs,挂载/sys目录(1、将设备分类、分层统一进行管理;2、配合udev/mdev守护进程动态创建设备文件,命名规则自由制定);
二、sysfs概述
linux系统通过sysfs体现设备驱动模型
- sysfs是一个虚拟文件系统(类似proc文件系统)
- 目录对应的inode节点会记录基本驱动对象(kobject),从而将系统中的设备组成层级结构
- 用户可以读写目录下不同文件来配置驱动对象(kobject)的不同属性
设备驱动模型基本元素
- kobject:sysfs中的一个目录,常用来表示基本驱动对象,不允许发送消息到用户空间
- kset:sysfs中的一个目录,常用来管理kobject,允许发送消息到用户空间
- kobj_type:目录下属性文件的操作接口
驱动模型一
- kset可以批量管理kobject
- kobject无法批量管理kobject
驱动模型二
kobject
sysfs中每一个目录都对应一个kobject
/home/geralt/linux_driver/kernel/ebf_linux_kernel_6ull_depth1/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 {
// 用于将起中的kobject对象构成链表
struct list_head list;
// 自旋锁
spinlock_t list_lock;
// 当前kset内核对象的kobject变量
struct kobject kobj;
// 定义一组函数指针,当kset中的某些kobject对象发生状态变化时需要通知用户空间时候,调用其中的函数来完成
const struct kset_uevent_ops *uevent_ops;
} __randomize_layout;
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);
};