Linux设备模型交互机制详细分析
Linux设备模型交互机制详细分析
概述
本文档深入分析Linux设备模型中kset、kobject、device等组件的交互机制,包括初始化流程、生命周期管理、事件处理和sysfs映射等核心机制。
1. kobject生命周期管理机制
1.1 kobject初始化流程图
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等核心组件的精妙配合,实现了:
- 统一的对象管理: 所有设备对象都基于kobject,提供统一的引用计数和生命周期管理
- 层次化的组织结构: 通过kset容器和parent指针构建清晰的设备树
- 透明的sysfs映射: 内核对象层次直接映射到用户空间可见的文件系统
- 灵活的事件通知: uevent机制实现内核到用户空间的异步事件通知
- 动态的驱动绑定: 支持设备和驱动的热插拔和动态匹配