当前位置: 首页 > article >正文

linux 内核结构基础

linux 内核对象基础

    • 1.linux 的 kobj(struct kobject) 类
    • 2.linux 中的 kset
    • 3. linux 下的 ktype (kobj_type 类)
    • 4. kobj 的使用理解

1.linux 的 kobj(struct kobject) 类

kobj 是 linux 下的高级抽象类定义,用于派生所有其余的类定义,比如设备类定义struct device.

struct kobject 定义在 include/linux/kobject.h 文件中:

struct kobject {
	const char		*name;
	struct list_head	entry;
	struct kobject		*parent;
	struct kset		*kset;
	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;
	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;
};

kobj 成员说明:

成员描述
namekobj 名字,会显示在 /sys/ 目录下
entry双向链接节点,用于被链入所属的 kset
parent指向 parent kobj, 在 /sys/ 中会以目录的形式呈现
kset当前 kobj 所属的 kset,kset 是一个特殊的 kobj, 用来集合相似的 kobj,表示父目录
ktype每一个 kobj 都必须有一个 ktype,用于访问该内核文件特有的属性,用于生成目录下的文件,以及实现文件读写驱动
sd当前 kobj 在 sysfs 中的目录入口,用于表示文件对象节点对象,kernfs_node 结构体中的 priv 成员会设置为 kobject 对象。
krefkobj 引用计数
state_initialized初始化状态
state_in_sysfs当前 kobj 是否已在 /sys/ 中呈现
state_add_uevent_sent记录是否已经向用户空间发送 uevent
state_remove_uevent_sent记录移除节点时,是否向用户空间发送 remove uevent
uevent_suppress是否忽略所有的用户空间事件上报,即事件通知

2.linux 中的 kset

kset 用于集合一系列相似的 kobj(类比某根目录?), 原型如下:

struct kset {
	struct list_head list;
	spinlock_t list_lock;
	struct kobject kobj;
	const struct kset_uevent_ops *uevent_ops;
} __randomize_layout;

kset 是一个特殊的 kobj,成员说明如下:

成员描述
list双向链表头,用于链接管理 kobj
list_lock自旋锁,防止接口竞争
kobjkset 是一个特殊的 kobj, kset 也会在 ‘/sys/’ 目录下出现
uevent_ops事件操作?

比如 /sys/bus/ 存在多个总线,bus 就属于一个 kset?

比如 /sys/class/ 存在多个 class,class 也属于一个 kset?

(似乎是的)

那么猜测: kset 用于表示 /sys/ 目录下的一级目录。

3. linux 下的 ktype (kobj_type 类)

ktype 用于实现 kobj 的一些特殊操作,比如释放 kobj 空间。

原型如下:

struct kobj_type {
	void (*release)(struct kobject *kobj);
	const struct sysfs_ops *sysfs_ops;
	struct attribute **default_attrs;	/* use default_groups instead */
	const struct attribute_group **default_groups;
	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);
};

最重要的 release 函数指针,用于释放 kobj空间。

sysfs_ops 用于访问当前 kobj 的属性文件。

/**
 * 作为 kobj_type 的成员,用于访问该内核对象下的属性文件的通用读写操作,而实际的属性读写函数,由驱动实现。
 * 一般用于内核层,比如内核总线、class 的属性访问方法,会调用实际总线、class 实现的属性访问方法
 */
struct sysfs_ops {
	ssize_t	(*show)(struct kobject *, struct attribute *, char *);
	ssize_t	(*store)(struct kobject *, struct attribute *, const char *, size_t);
};

struct attribute **default_attrs 为属性指针数组,该数组保存一系列的属性指针。

/* 内核文件的属性,一个属性对应一个文件 */
/**
 * 这是通用的属性对象,使用时会对该对象进行封装,比如总线属性,设备属性,一般会根据实际情况封装属性文件的读写方法。 
 */
struct attribute {
	const char		*name;
	umode_t			mode;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
	bool			ignore_lockdep:1;
	struct lock_class_key	*key;
	struct lock_class_key	skey;
#endif
};

还存在一个 struct attribute_group 类,用于存储一组属性,但用法没有研究透。

struct attribute_group {
	const char		*name;
	umode_t			(*is_visible)(struct kobject *,
					      struct attribute *, int);
	umode_t			(*is_bin_visible)(struct kobject *,
						  struct bin_attribute *, int);
	struct attribute	**attrs;
	struct bin_attribute	**bin_attrs;
};

代码分析:根据 sysfs_create_groups() 函数实现,如果 struct attribute_group name 成员实现,那么会在指定的 kobj 对象下另建一个 group 目录,并在 group 目录下创建所有的可见属性文件。

4. kobj 的使用理解

kobj 大多时候是嵌入到高级数据结构中,比如设备定义 struct device 中。

这些高级数据结构一般是动态分配的,当内嵌的 kobj 的引用计数 kref 减为 0 时,需要释放高级数据结构所占内存,以及对应的 kobj 内存。

此时,需要使用 kobj 中 ktype 定义的 release 函数指针。

所以,每一个包含 kobj 的高级数据结构,都必须实现所属的 ktype。

基于面向对象编程的思想,系统用户看到的只有 kobj,而不会看到驱动相关的数据结构。

以访问 /sys/ 下的文件举例, 基于一切皆文件的思想,linux 用户向/sys访问 kobj 的流程如下:

应用层linux应用层 open\read\write\close 访问文件
VFS/kernfslinux VFS 文件系统根据文件所属的实际文件系统,调用 sysfs 文件系统的 open\read\write\close
sysfssysfs 文件系统的实际驱动根据获取 kobj 对象,并调用 kobj 提供的属性(文件)访问接口
kobjkobj 调用驱动层提供的属性访问接口。
驱动驱动对私有属性的实现。

以访问字符设备 /dev/tty0举例, 基于一切皆文件的思想,linux 用户向/dev/tty0访问 kobj 的流程如下:

应用层linux应用层 open\read\write\close 访问文件
VFS/kernfslinux VFS 文件系统根据文件所属的实际文件系统,获取 knode, 并调用设备文件系统的 open\read\write\close
设备文件系统?设备文件系统根据 knode 结构获取 kobj 结构,并转换为 cdev 结构,然后直接调用驱动注册的 open/read/write/close
驱动驱动对open\read\write\close的实现。

kobj 是系统内核能访问的最底层数据结构,其余结构都是对 kobj 的再封装。

Linux应用层访问驱动自定义class属性流程如下:
在这里插入图片描述

应用层到系统内核层:

  1. 应用层使用 open/read/write/close 访问某一文件系统的文件, 系统调用;

  2. Kernfs 层根据文件系统类型调用文件系统的驱动,并获取当前文件的 knode 结构,文件的 knode 结构是对 kobj 的再封装(knode 对象与 kobj 对象相互引用);

  3. Sysfs 层会通过 knode 结构获取 kobj 结构,并调用文件(属性)的读/写;

  4. Kobj 层会调用属性访问驱动将对应属性传递到 class 层;

驱动层:

驱动层会自定义 class 属性,并定义属性访问函数;实现驱动变量的控制

  1. Class 层接收内核层对某一属性的读写访问,实现由应用层来控制驱动变量的值,控制驱动行为。

  2. 驱动根据属性变量值,做出不同的行为。

注意:

  1. 每一个驱动自定义 class 属性都会生成一个文件,通过调用 class_create_file()。
  2. class 层是对 kobj 的封装层,源码比较容易理解.

http://www.kler.cn/a/543213.html

相关文章:

  • 关于 IoT DC3 中设备(Device)的理解
  • 计算机组成原理
  • 游戏引擎学习第100天
  • Shell-基本命令与运算符
  • 用户认证综合实验
  • 国产编辑器EverEdit - 编辑辅助功能介绍
  • MFC程序设计(十二)绘图
  • 建筑兔零基础自学python记录18|实战人脸识别项目——视频检测07
  • EPL 4.01 Preview
  • 【Elasticsearch】文本分析Text analysis概述
  • 【鸿蒙开发】第二十九章 Stage模型-应用上下文Context、进程、线程
  • Unity 代码优化记录
  • 【c++】shared_ptr是线程安全的吗?
  • fun-transformer学习笔记-Task1——Transformer、Seq2Seq、Encoder-Decoder、Attention之间的关系
  • vivo手机和Windows电脑连接同一个WiFi即可投屏!
  • Spring Cloud 完整引解:优化你的微服务架构
  • GEE批量打开asset权限(anyone can read)
  • YOLOv11融合[AAAI2025]的Mesorch 模型中的高、低频特征提取模块
  • kafka在初始化集群配置当中有哪些重要参数?
  • (定时器,绘制事件,qt简单服务器的搭建)2025.2.11
  • vuedraggable固定某一item的记录
  • 语言大模型基础概念 一(先了解听说过的名词都是什么)
  • 元宵佳节,我的创作纪念日:技术之路的回顾与展望
  • 【多模态大模型】系列1:Transformer Encoder——ViLT、ALBEF、VLMO
  • MVC(Model-View-Controller)framework using Python ,Tkinter and SQLite
  • 机器学习数学基础:22.对称矩阵的对角化