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

Linux设备模型交互机制详细分析

Linux设备模型交互机制详细分析

概述

本文档深入分析Linux设备模型中kset、kobject、device等组件的交互机制,包括初始化流程、生命周期管理、事件处理和sysfs映射等核心机制。

1. kobject生命周期管理机制

1.1 kobject初始化流程图

kobject_init
设置ktype
初始化kref=1
初始化list_head
设置状态标志
kobject_add
设置name
设置parent
加入kset链表
创建sysfs节点
发送ADD uevent

1.2 引用计数管理机制

// 引用计数操作核心代码分析
struct kobject *kobject_get(struct kobject *kobj)
{if (kobj) {if (!kref_get_unless_zero(&kobj->kref))kobj = NULL;}return kobj;
}void kobject_put(struct kobject *kobj)
{if (kobj) {kref_put(&kobj->kref, kobject_release);}
}static void kobject_release(struct kref *kref)
{struct kobject *kobj = container_of(kref, struct kobject, kref);// 调用ktype->release()if (kobj->ktype && kobj->ktype->release)kobj->ktype->release(kobj);
}

1.3 引用计数流转图

                    kobject引用计数生命周期创建时           获取引用         释放引用         销毁时kref=1    -->    kref++    -->    kref--    -->   kref=0│                │               │               │▼                ▼               ▼               ▼┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐│ CREATED │    │ ACTIVE  │    │ ACTIVE  │    │RELEASED ││         │    │         │    │         │    │         ││kobject_ │    │kobject_ │    │kobject_ │    │ktype->  ││init()   │    │get()    │    │put()    │    │release()│└─────────┘    └─────────┘    └─────────┘    └─────────┘

2. kset容器管理机制

2.1 kset操作流程

// kset核心操作代码分析
struct kset *kset_create_and_add(const char *name,const struct kset_uevent_ops *uevent_ops,struct kobject *parent_kobj)
{struct kset *kset;int error;kset = kset_create(name, uevent_ops, parent_kobj);if (!kset)return NULL;error = kset_register(kset);if (error) {kfree(kset);return NULL;}return kset;
}static void kset_release(struct kobject *kobj)
{struct kset *kset = container_of(kobj, struct kset, kobj);// 清理kset资源kfree(kset);
}

2.2 kset层次结构管理图

                    kset层次结构管理机制┌─────────────────┐│   kernel_kobj   │ (根kobject)└─────────┬───────┘│ parent▼┌─────────────────────────────────────────────────────┐│                devices_kset                         ││  ┌─────────────────────────────────────────────┐    ││  │         embedded kobject                    │    ││  │  name: "devices"                           │    ││  │  parent: &kernel_kobj                     │    ││  │  ktype: &kset_ktype                       │    ││  └─────────────────────────────────────────────┘    ││                                                     ││  ┌─────────────────────────────────────────────┐    ││  │              list                           │    ││  │   ┌──────────┐  ┌──────────┐  ┌──────────┐  │    ││  │   │device1   │  │device2   │  │device3   │  │    ││  │   │.entry    │  │.entry    │  │.entry    │  │    ││  │   │.kset ────┼──┼.kset ────┼──┼.kset ────┼──┼────┼┐│  │   └──────────┘  └──────────┘  └──────────┘  │    │││  └─────────────────────────────────────────────┘    │││                                                     │││  uevent_ops: &device_uevent_ops                     ││└─────────────────────────────────────────────────────┘││┌─────────────────────────────────────────────────────┐││             同级kset: bus_kset                      │││             同级kset: class_kset                    │││             同级kset: fs_kset                       ││└─────────────────────────────────────────────────────┘││关联 ◄──────────────────────────┘

3. device与kobject集成机制

3.1 device初始化流程

// device初始化核心代码
void device_initialize(struct device *dev)
{dev->kobj.kset = devices_kset;  // 加入devices_ksetkobject_init(&dev->kobj, &device_ktype);  // 初始化嵌入的kobjectINIT_LIST_HEAD(&dev->devres_head);device_pm_init(dev);set_dev_node(dev, -1);// ... 其他初始化
}int device_add(struct device *dev)
{// 1. 设置kobject名称if (dev->init_name) {dev_set_name(dev, "%s", dev->init_name);dev->init_name = NULL;}// 2. 设置父设备关系if (dev->parent)dev->kobj.parent = &dev->parent->kobj;// 3. 添加到kobject层次结构error = kobject_add(&dev->kobj, dev->kobj.parent, NULL);// 4. 添加到各个子系统if (dev->bus)bus_add_device(dev);if (dev->class)device_add_class_symlinks(dev);// 5. 创建属性文件device_add_attributes(dev, dev->class);return 0;
}

3.2 device与各子系统关联图

                    device与子系统关联机制┌─────────────────────────────────────────────────────┐│                    device                           ││  ┌─────────────────────────────────────────────┐    ││  │            kobject                          │    ││  │  name: "eth0"                              │    ││  │  parent: &pci_device.kobj                  │    ││  │  kset: devices_kset                        │    ││  │  ktype: &device_ktype                      │    ││  └─────────────────────────────────────────────┘    ││                                                     ││  bus: &pci_bus_type ────────────────────────────────┼─┐│  driver: &e1000_driver ─────────────────────────────┼─┼─┐│  class: &net_class ─────────────────────────────────┼─┼─┼─┐│  parent: &pci_device ───────────────────────────────┼─┼─┼─┼─┐└─────────────────────────────────────────────────────┘ │ │ │ ││ │ │ │device_private                 │ │ │ │┌─────────────────────────────────────────────────────┐ │ │ │ ││  knode_bus    ──────────────────────────────────────┼─┘ │ │ ││  knode_driver ──────────────────────────────────────┼───┘ │ ││  knode_class  ──────────────────────────────────────┼─────┘ ││  knode_parent ──────────────────────────────────────┼───────┘│  klist_children                                     ││  device: &device                                    │└─────────────────────────────────────────────────────┘│▼┌─────────────────────────────────────────────────────┐│                pci_bus_type                         ││  ┌─────────────────────────────────────────────┐    ││  │          subsys_private                     │    ││  │   klist_devices contains device             │    ││  │   klist_drivers contains drivers            │    ││  └─────────────────────────────────────────────┘    │└─────────────────────────────────────────────────────┘│▼┌─────────────────────────────────────────────────────┐│               e1000_driver                          ││  ┌─────────────────────────────────────────────┐    ││  │          driver_private                     │    ││  │   klist_devices contains device             │    ││  └─────────────────────────────────────────────┘    │└─────────────────────────────────────────────────────┘│▼┌─────────────────────────────────────────────────────┐│                 net_class                           ││  ┌─────────────────────────────────────────────┐    ││  │          subsys_private                     │    ││  │   klist_devices contains device             │    ││  └─────────────────────────────────────────────┘    │└─────────────────────────────────────────────────────┘

4. sysfs映射机制

4.1 sysfs文件系统映射流程

// sysfs映射核心代码
int kobject_add(struct kobject *kobj, struct kobject *parent, const char *fmt, ...)
{// 1. 设置名称和父对象kobj->parent = parent;// 2. 创建sysfs目录error = create_dir(kobj);if (error)return error;// 3. 加入kset链表kobj_kset_join(kobj);// 4. 发送uevent事件kobject_uevent(kobj, KOBJ_ADD);return 0;
}static int create_dir(struct kobject *kobj)
{const struct kobj_type *ktype = get_ktype(kobj);// 创建kernfs节点kobj->sd = kernfs_create_dir(parent_sd, kobj->name, 0755, kobj);// 创建默认属性文件if (ktype && ktype->default_groups) {error = sysfs_create_groups(kobj, ktype->default_groups);}return 0;
}

4.2 sysfs目录结构映射图

                    sysfs目录结构映射机制内核对象层次                     sysfs文件系统kernel_kobj                      /sys/│                              │▼                              ▼devices_kset ────────────────→  /sys/devices/│                              │├─device1 ───────────────→     ├─pci0000:00/│   │                          │    ││   ├─kobject.name="pci..."    │    ├─0000:00:1f.2/│   ├─attribute1               │    │    ├─vendor│   ├─attribute2               │    │    ├─device  │   └─child_device ──────────→ │    │    └─subsystem -> ../../bus/pci│                              │    │├─device2 ───────────────→     ├─platform/│                              │    │└─device3 ───────────────→     └─virtual/│bus_kset ────────────────────→  /sys/bus/│                              │├─pci_bus ──────────────→      ├─pci/│   │                          │   ├─devices/│   ├─devices_kset              │   │   ├─0000:00:1f.2 -> ../../../devices/pci0000:00/0000:00:1f.2│   └─drivers_kset              │   │   └─...│                              │   └─drivers/└─platform_bus ─────────→      │       ├─e1000/│       └─...└─platform/class_kset ──────────────────→  /sys/class/│                              │├─net_class ────────────→      ├─net/│   │                          │   ├─eth0 -> ../../devices/pci0000:00/0000:00:1f.2/net/eth0│   └─devices_kset              │   └─...│                              │└─block_class ──────────→      └─block/├─sda -> ../../devices/pci0000:00/0000:00:1f.2/ata1/host0/target0:0:0/0:0:0:0/block/sda└─...

5. uevent事件机制

5.1 uevent事件流程

// uevent事件处理核心代码
int kobject_uevent(struct kobject *kobj, enum kobject_action action)
{return kobject_uevent_env(kobj, action, NULL);
}int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,char *envp_ext[])
{struct kobj_uevent_env *env;struct kset_uevent_ops *uevent_ops;// 1. 检查是否抑制事件if (kobj->uevent_suppress)return 0;// 2. 找到顶层ksettop_kobj = kobj;while (!top_kobj->kset && top_kobj->parent)top_kobj = top_kobj->parent;// 3. 获取uevent操作集uevent_ops = top_kobj->kset->uevent_ops;// 4. 过滤事件if (uevent_ops && uevent_ops->filter) {if (!uevent_ops->filter(kobj))return 0;}// 5. 构建环境变量env = kzalloc(sizeof(*env), GFP_KERNEL);// 添加标准环境变量add_uevent_var(env, "ACTION=%s", kobject_actions[action]);add_uevent_var(env, "DEVPATH=%s", devpath);add_uevent_var(env, "SUBSYSTEM=%s", subsystem);// 6. 调用自定义uevent处理if (uevent_ops && uevent_ops->uevent) {retval = uevent_ops->uevent(kobj, env);}// 7. 发送netlink消息到用户空间netlink_broadcast_filtered(uevent_sock, skb, ...);return 0;
}

5.2 uevent事件传播图

                    uevent事件传播机制内核空间                                用户空间┌─────────────────┐                   ┌─────────────────┐│   kobject       │                   │     udevd       ││                 │                   │                 ││ kobject_uevent()│ ──────────────────┤                 │└─────────┬───────┘                   │  netlink socket ││                           │                 │▼                           │                 │┌─────────────────┐                   │                 ││ kset_uevent_ops │                   │                 ││                 │                   │                 ││ ├─filter()      │                   │                 ││ ├─name()        │                   │                 ││ └─uevent()      │                   │                 │└─────────┬───────┘                   │                 ││                           │                 │▼                           │                 │┌─────────────────┐    netlink        │                 ││ netlink_broadcast│ ─────────────────►│                 ││                 │                   │                 ││ ACTION=add      │                   │                 ││ DEVPATH=/devices│                   │                 ││ SUBSYSTEM=net   │                   │                 ││ DEVTYPE=...     │                   │                 │└─────────────────┘                   └─────────────────┘│▼┌─────────────────┐│   用户空间处理   ││                 ││ ├─创建设备节点   ││ ├─加载模块      ││ ├─设置权限      ││ └─运行脚本      │└─────────────────┘

6. 设备驱动绑定机制

6.1 driver-device匹配流程

// 驱动设备匹配核心代码
static int device_attach(struct device *dev)
{if (dev->driver) {// 设备已有驱动device_bind_driver(dev);return 1;}// 在总线上查找匹配的驱动return bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
}static int __device_attach(struct device_driver *drv, void *data)
{struct device *dev = data;// 检查驱动是否匹配设备if (!driver_match_device(drv, dev))return 0;// 尝试绑定return driver_probe_device(drv, dev);
}static inline int driver_match_device(struct device_driver *drv,struct device *dev)
{return drv->bus->match ? drv->bus->match(dev, drv) : 1;
}

6.2 驱动设备绑定状态图

                    驱动设备绑定状态转换图设备状态        事件           驱动状态         结果┌─────────┐   device_add    ┌─────────┐     ┌─────────┐│ CREATED │ ─────────────── │AVAILABLE│ ──► │ PROBING │└─────────┘                 └─────────┘     └─────────┘│                           │               ││ driver_register            │ match()       │ probe()▼                           ▼               ▼┌─────────┐                 ┌─────────┐     ┌─────────┐│UNBOUND  │ ◄─────────────── │MATCHING │ ──► │ BOUND   │└─────────┘   probe_failed   └─────────┘     └─────────┘▲                                           ││ device_release_driver                     │ device_remove└───────────────────────────────────────────┘状态说明:CREATED: 设备已创建但未添加到系统UNBOUND: 设备在系统中但未绑定驱动AVAILABLE: 驱动可用等待设备MATCHING: 正在进行匹配过程PROBING: 正在执行probe函数BOUND: 设备和驱动成功绑定

7. 总结

Linux设备模型通过kobject、kset、device等核心组件的精妙配合,实现了:

  1. 统一的对象管理: 所有设备对象都基于kobject,提供统一的引用计数和生命周期管理
  2. 层次化的组织结构: 通过kset容器和parent指针构建清晰的设备树
  3. 透明的sysfs映射: 内核对象层次直接映射到用户空间可见的文件系统
  4. 灵活的事件通知: uevent机制实现内核到用户空间的异步事件通知
  5. 动态的驱动绑定: 支持设备和驱动的热插拔和动态匹配
http://www.xdnf.cn/news/18394.html

相关文章:

  • 突击复习清单(高频核心考点)
  • RORPCAP: retrieval-based objects and relations prompt for image captioning
  • STM32F103RC的USB上拉电阻1.5K
  • 回归测试的重要性与实践指南
  • 52 C++ 现代C++编程艺术1-禁止隐式转换关键字explicit
  • go语言中的select的用法和使用场景
  • Maven初识到应用
  • nginx-如何卸载和升级编译安装的版本
  • 第4课:布局与样式
  • RabbitMQ 应用问题
  • 产教融合助企业:国际数字影像产业园办全媒体人才培育会
  • K8S管理实战指南
  • 如何实现H5页面拉起原生App?
  • 学习:uniapp全栈微信小程序vue3后台(3)
  • SprintBoot 2 源码阅读
  • Thunderbird 将推出在德国托管的加密电子邮件服务
  • 浏览器插件优化工具:bypass paywalls chrome
  • 力扣热题之贪心算法
  • Python 办公自动化实战:Excel 批量处理 + 自动发邮件
  • VsCode 上的Opencv(C++)环境配置(Linux)
  • 51单片机-中断系统
  • Ansys Motor-CAD:概述(EMag、THERM、LAB、MECH)
  • 171-基于Flask的笔记本电脑数据可视化分析系统
  • Linux数字列排序命令
  • Apache Ozone 介绍与部署使用(最新版2.0.0)
  • 大数据毕业设计推荐:基于Hadoop+Spark的手机信息分析系统完整方案
  • Matrix-Zero:昆仑万维发布的AI世界模型,支持单张图生成3D世界
  • 微信小程序,事件总线(Event Bus) 实现
  • 不同类型代理 IP 在爬虫场景下的表现对比
  • 05 ODS层(Operation Data Store)