100 linux 设备驱动模型

一、为什么需要设备驱动模型

早期内核(2.4之前)没有统一的设备驱动模型,但照样可以用。需要手动调用 mknod 指令创建设备文件,绑定了 file_operation 后才能调用驱动控制硬件,很不方便。

2.4~2.6期间使用devfs,就是设备文件系统,挂载在/dev目录。
需要在内核驱动中创建设备文件(devfs_register,参数为设备文件名),不再需要手动使用 mknod 指令来创建设备文件。
但这种方式命名死板。

2.6以后使用sysfs,挂载在/sys目录下。
将设备分类、分层统一进行管理。
配合 udev / mdev 守护进程动态创建设备文件,命令规则自由制定。

二、sysfs概述

linux系统通过sysfs体现出设备驱动模型。

sysfs是一个 虚拟文件系统(类似proc文件系统)。一个用来体现设备驱动模型(上面的分类和层次关系),一个用来展示进程方面的相关消息。
目录 对应的 inode节点 会记录基本驱动对象(kobject),从而将系统中的设备组成层次结构。
一个kobject对象 与 sysfs中的一个目录 对应。
linux把目录也抽象成inode节点:普通文件的inode节点就是用来记录这个文件的内容;目录节点用来记录这个目录下面的所有文件的相关信息。
所有的复杂的设备都会继承这个 kobject 对象。struct cdev 也继承了 struct kobject。

用户可以读写kobject对应的目录下的不同文件来配置驱动对象(kobject)的不同属性。

三、设备驱动模型3个基本元素

kobject:sysfs中的一个目录,常用来表示基本驱动对象,不允许发送消息到用户空间。守护进程udev 或者 守护进程mdev 会监控驱动程序发出来的消息。kobject不允许发送消息给 udev 或 mdev。

kset:sysfs中的一个目录,常用来管理 kobject 或者 另一个 kset,允许发送消息到用户空间。

kobj_type:一个kobject对应一个目录,这个目录下属性文件的操作接口。

1、kobject

sysfs中每一个目录都对应一个kobject

include/linux/kobject.h

struct kobject {
	//用来表示该 kobject 的名称,sysfs 目录下的目录名称。
	const char		*name;
	//链表节点,将 kobject 串联起来进行管理。
	struct list_head	entry;
	//该 kobject 的上层节点,构建 kobject 之间的层次关系。
	struct kobject		*parent;
	//该 kobject 所属的 kset 对象,kset对象 用于批量管理 kobject 对象。
	struct kset		*kset;
	//该 kobject 的 sysfs 文件系统相关的操作和属性接口。下面有详细介绍。
	struct kobj_type	*ktype;
	//指向该 kobject 在 sysfs 文件系统中对应目录项。由此实现一个kobject对应一个目录。
	struct kernfs_node	*sd; /* sysfs directory entry */
	//该 kobject 的引用次数。
	struct kref		kref;
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
	struct delayed_work	release;
#endif
	//记录内核对象 kobject 的初始化状态,赋1表示已经初始化。
	unsigned int state_initialized:1;
	//表示该 kobject 所代表的内核对象有没有在 sysfs 建立相应目录,赋1表示建立了目录。
	unsigned int state_in_sysfs:1;
	//下面3个适合发送消息到用户空间相关。
	unsigned int state_add_uevent_sent:1;
	unsigned int state_remove_uevent_sent:1;
	unsigned int uevent_suppress:1;
};

2、kset

struct kset {
	//链表头,用来将管理的 kobject  对象构建成链表
	struct list_head list;
	//自旋锁,确保 kset 的互斥访问。
	spinlock_t list_lock;
	//当前kset内核对象继承的 kobject 对象。
	struct kobject kobj;
	//定义了一组函数指针,当kset中的某些kobject对象发生状态变化需要通知用户空间时,调用其中的函数来完成。
	const struct kset_uevent_ops *uevent_ops;
}

3、kobj_type

用来记录 kobject 对象关联的 sysfs下的目录 下面的文件操作接口。

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);
};

四、两种驱动模型

1、驱动模型一

kset 会继承一个kobject。
子kset的kobject成员的parent节点 会设置为 父kset的kobject成员。
利用 parent指针 来体现层次关系。
kobject 的 kset指针指向 管理它的 kset。
在这里插入图片描述

kset可批量管理kobject

kobject无法批量管理kobject

2、驱动模型二

此时下层的 kobject 可以找到上层的 kobject;但是此时上层的kobject 无法找到 下层的kobject(不像上面的kset包含一个链表头)。
所以此模型虽然简单但是很少用。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QVFwWrrA-1623588093700)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20200810195127363.png)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值