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 引用计数管理机制

c 复制代码
// 引用计数操作核心代码分析
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 引用计数流转图

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

2. kset容器管理机制

2.1 kset操作流程

c 复制代码
// 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层次结构管理图

text 复制代码
                    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初始化流程

c 复制代码
// device初始化核心代码
void device_initialize(struct device *dev)
{
    dev->kobj.kset = devices_kset;  // 加入devices_kset
    kobject_init(&dev->kobj, &device_ktype);  // 初始化嵌入的kobject
    INIT_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与各子系统关联图

text 复制代码
                    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文件系统映射流程

c 复制代码
// 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目录结构映射图

text 复制代码
                    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事件流程

c 复制代码
// 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. 找到顶层kset
    top_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事件传播图

text 复制代码
                    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匹配流程

c 复制代码
// 驱动设备匹配核心代码
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 驱动设备绑定状态图

text 复制代码
                    驱动设备绑定状态转换图
                    
    设备状态        事件           驱动状态         结果
    
    ┌─────────┐   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. 动态的驱动绑定: 支持设备和驱动的热插拔和动态匹配