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等核心组件的精妙配合,实现了:
- 统一的对象管理: 所有设备对象都基于kobject,提供统一的引用计数和生命周期管理
- 层次化的组织结构: 通过kset容器和parent指针构建清晰的设备树
- 透明的sysfs映射: 内核对象层次直接映射到用户空间可见的文件系统
- 灵活的事件通知: uevent机制实现内核到用户空间的异步事件通知
- 动态的驱动绑定: 支持设备和驱动的热插拔和动态匹配