linux驱动基础知识-白阳(三) KOBJECT引用计数


kobject主要功能:1,提供设备的引用计数, 2,提供sysfs支持 3,提供热插拔机制
kobject 提供了基本的对象管理能力,是构成 Linux 2.6 设备模型的核心结构,每个在内核中注册的 kobject 对象都对应于 sysfs 文件系统中的一个目录


linux/kobject.h
linux/kerf.h
linux/refcount.h

lib/kobject.c 和lib/kobject_uevent.c; 事件部分以后再看

一、:引用计数-这里是个原子变量,具有原子的读写、设置等
typedef struct refcount_struct {
atomic_t refs;
} refcount_t;


struct kref {
refcount_t refcount; //引用计数 ,原子变量  atomic_t refs;
};

二、当前链表节点,用来挂载到kset的部分
struct list_head entry;

三、 struct kobj_type 对象类型 ,与sysfs 挂钩
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *, char *);
ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
};
sysfs_ops 包括 store()和 show()两个成员函数,用于实现属性的读写
当从用户空间读取属性时, show()函数将被调用,该函数将指定属性值存入 buffer 中返回给用户; store()函数用于存储用户通过 buffer 传入的属性值。

kobject 不同的是, 属性在 sysfs 中呈现为一个文件,而 kobject 则呈现为 sysfs 中的目录 ???!!!不太懂

struct kobj_type {
void (*release)(struct kobject *kobj); //释放 kobject 占用的资源的 release()函数
const struct sysfs_ops *sysfs_ops; //sysfs_ops 包括 store()和 show()两个成员函数,用于实现属性的读写

struct attribute **default_attrs; // sysfs 文件系统默认属性列表
const struct kobj_ns_type_operations *(*child_ns_type)(struct kobject *kobj);
const void *(*namespace)(struct kobject *kobj);
};


void kobject_init(struct kobject *kobj, struct kobj_type *ktype);
//初始化 引用计数为1和初始化状态,初始化链表头,初始化ktype类型

四、
kset 具有相同类型的 kobject 的集合,根types来区别
/**
* struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.
*
* A kset defines a group of kobjects. They can be individually
* different "types" but overall these kobjects all want to be grouped
* together and operated on in the same manner. ksets are used to
* define the attribute callbacks and other common events that happen to
* a kobject.
*
* @list: the list of all kobjects for this kset
* @list_lock: a lock for iterating over the kobjects
* @kobj: the embedded kobject for this kset (recursion, isn't it fun...)
* @uevent_ops: the set of uevent operations for this kset. These are
* called whenever a kobject has something happen to it so that the kset
* can add new environment variables, or filter out the uevents if so
* desired.
*/
struct kset {
struct list_head list; //用于连接该 kset 中所有 kobject 的链表头
spinlock_t list_lock;
struct kobject kobj; ///嵌入的 kobject,kset的引用计数就是实际上就是内嵌的 kobject 对象的引用计数
const struct kset_uevent_ops *uevent_ops; //事件操作集
} __randomize_layout;


struct kset_uevent_ops {
int (* const filter)(struct kset *kset, struct kobject *kobj); //事件过滤
const char *(* const name)(struct kset *kset, struct kobject *kobj);
int (* const uevent)(struct kset *kset, struct kobject *kobj,
struct kobj_uevent_env *env); //环境变量设置
};
Linux 提供一系列函数操作 kset。 kset_init()完成指定 kset 的初始化, kset_get()和
kset_put()分别增加和减少 kset 对象的引用计数, kset_add()和 kset_del()函数分别实现将指定 keset 对象
加入设备层次和从其中删除, kset_register()函数完成 kset 的注册, kset_unregister()函数则完成 kset 的
注销。




五、kobject
struct kobject {
const char *name;
struct list_head entry; //kobject用来挂载到kset同类对象的链表节点,
struct kobject *parent; //父类kobject,指向所属kset的kobject
struct kset *kset; //同类kobject的集合

struct kobj_type *ktype; //类型
struct kernfs_node *sd; /* sysfs directory entry */
struct kref kref; //对象引用计数*******原子变量
#ifdef CONFIG_DEBUG_KOBJECT_RELEASE
struct delayed_work release;
#endif
unsigned int state_initialized:1; //初始化时被设置为1,避免多次初始化
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;
};
Linux 内核中提供一系列操作 kobject 的函数:
void kobject_init(struct kobject * kobj);
该函数用于初始化 kobject,它设置 kobject 引用计数为1, entry 链表初始化

int kobject_set_name(struct kobject *kobj, const char *format, ...);
该函数用于设置指定 kobject 的名称。
//例如:retval = kobject_set_name(&kset->kobj, "%s", name);


void kobject_cleanup(struct kobject * kobj)和 void kobject_release(struct kref *kref);
该函数用于清除 kobject,当其引用计数为0时,释放对象占用的资源。(也就是调用ktype中的release方法)

struct kobject *kobject_get(struct kobject *kobj);
该函数用于将 kobj 对象的引用计数加 1,同时返回该对象的指针。

void kobject_put(struct kobject * kobj);
该函数用于将 kobj 对象的引用计数减 1,如果引用计数降为 0,则调用 kobject_release()释放该 kobject对象。

int kobject_add(struct kobject *kobj, struct kobject *parent, kobj_ns_drop const char *fmt, ...)
该函数用于将 kobject 对象加入 Linux 设备层次,它会挂接该 kobject 对象到 kset 的 list 链中,增加父
目录各级 kobject 的引用计数,在其 parent 指向的目录下创建文件节点,并启动该类型内核对象的 hotplug函数。
创建sysfs文件

struct kobject *kobject_create_and_add(const char *name, struct kobject *parent)
该函数用于注册 kobject,它会先调用 kobject_init()初始化 kobj,再调用 kobject_add()完成该内核对象的添加。
调用完成后 ,使用kobject_put会自动释放内存

kobject_del()从设备层次中删除该对象,再调用 kobject_put()减少该对象的引用计数,如果引用计数降为 0,则释放该 kobject 对象。

#注:这里只是自己整理了部分,需要用时看那几个头文件和实现;或者参考宋宝华老师的《Linux设备驱动开发详解》第四章;;

猜你喜欢

转载自blog.csdn.net/sven0223/article/details/81324195