欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > dpm_sysfs_add

dpm_sysfs_add

2025/5/5 12:03:31 来源:https://blog.csdn.net/jojopinjiaoku/article/details/147700566  浏览:    关键词:dpm_sysfs_add

这段代码是 Linux 内核中**设备电源管理(PM)子系统**与 **sysfs 文件系统**交互的核心实现,主要功能是为设备创建电源管理相关的 sysfs 属性文件。以下从五个关键维度进行深度解析:

---

### 一、功能架构全景
```mermaid
graph TD
    A[dpm_sysfs_add] --> B[创建基础PM属性组]
    B --> C{运行时PM支持?}
    C -->|是| D[合并运行时PM属性组]
    C -->|否| E{支持唤醒?}
    D --> E
    E -->|是| F[合并唤醒属性组]
    E -->|否| G{支持延迟容忍?}
    F --> G
    G -->|是| H[合并QoS延迟属性组]
    G -->|否| I[完成]
```

---

### 二、核心机制解析

#### 1. **属性组分层管理**
| 属性组类型                  | 作用域               | 典型属性文件                | 触发条件                     |
|----------------------------|----------------------|---------------------------|----------------------------|
| `pm_attr_group`            | 所有设备             | `async`/`control`         | 强制添加                    |
| `pm_runtime_attr_group`    | 支持运行时PM的设备    | `runtime_enabled`/`status`| `pm_runtime_callbacks_present()`|
| `pm_wakeup_attr_group`     | 可唤醒设备           | `wakeup`/`wakeup_count`   | `device_can_wakeup()`       |
| `pm_qos_latency_tolerance` | 支持延迟控制的设备    | `latency_tolerance`       | `dev->power.set_latency_tolerance`|

#### 2. **sysfs操作关键区别**
| 操作类型             | 函数                  | 特点                                                                 |
|----------------------|-----------------------|----------------------------------------------------------------------|
| **创建新组**         | `sysfs_create_group`  | 严格创建新目录和文件,若已存在则报错                                 |
| **合并到现有组**     | `sysfs_merge_group`   | 将新属性追加到已有目录,原子性操作(全部成功或全部回滚)             |

#### 3. **错误处理策略**
采用**阶梯式回滚**:
```c
err_wakeup:
    sysfs_unmerge_group(..., &pm_wakeup_attr_group);
err_runtime:
    sysfs_unmerge_group(..., &pm_runtime_attr_group);
err_out:
    sysfs_remove_group(..., &pm_attr_group);
```

---

### 三、内核对象关联
```mermaid
classDiagram
    class device {
        +struct kobject kobj
        +struct dev_pm_info power
    }
    class attribute_group {
        +struct attribute **attrs
        +is_visible()
    }
    class kernfs_node {
        +umode_t mode
        +const struct kernfs_ops *ops
    }
    device "1" --> "*" attribute_group : 包含
    attribute_group --> kernfs_node : 实例化为
```

---

### 四、关键代码路径

#### 1. **属性文件创建深度调用链**
```plaintext
dpm_sysfs_add()
  → sysfs_create_group()
    → internal_create_group()
      → kernfs_create_dir()      # 创建属性组目录
      → create_files()
        → sysfs_add_file_mode_ns()
          → __kernfs_create_file() # 最终创建文件节点

  → sysfs_merge_group()
    → kernfs_find_and_get()      # 查找已存在目录
    → sysfs_add_file()           # 追加新属性
```

#### 2. **权限控制实现**
```c
// 在 create_files() 中的权限处理
mode = grp->is_visible(kobj, *attr, i); // 回调决定最终mode
WARN(mode & ~(SYSFS_PREALLOC | 0664), ...); // 权限位检查
mode &= SYSFS_PREALLOC | 0664; // 强制有效权限
```

---

### 五、设计亮点与约束

#### 1. **动态属性可见性**
通过 `is_visible` 回调实现条件属性:
```c
// 示例:仅当设备支持休眠时才显示相关属性
static umode_t dev_pm_is_visible(struct kobject *kobj, struct attribute *attr, int n)
{
    if (!dev->power.sleep_ops && (attr == &dev_attr_hibernation.attr))
        return 0;
    return attr->mode;
}
```

#### 2. **原子性保证**
- `sysfs_merge_group` 在添加多个属性时,要么全部成功,要么全部回滚
- 通过错误处理中的 `while (--i >= 0)` 循环实现逆向删除

#### 3. **性能优化**
- **懒加载**:只有设备具备相应功能时才添加对应属性组(如运行时PM)
- **预分配标记**:`SYSFS_PREALLOC` 优化频繁访问的属性文件

#### 4. **安全约束
- 强制限制权限不超过 `0664`(防止危险权限设置)
- 锁依赖检查(`CONFIG_DEBUG_LOCK_ALLOC`)避免死锁

---

### 六、典型应用场景

#### 1. **PCI设备电源管理**
```bash
# 查看所有PCI设备的运行时PM状态
ls /sys/bus/pci/devices/*/power/control

# 启用自动挂起
echo auto > /sys/bus/pci/devices/0000:00:1f.2/power/control
```

#### 2. **USB设备唤醒功能**
```bash
# 检查唤醒能力
cat /sys/bus/usb/devices/1-1/power/wakeup

# 启用唤醒
echo enabled > /sys/bus/usb/devices/1-1/power/wakeup
```

#### 3. **延迟敏感型设备配置**
```bash
# 设置最大延迟容忍
echo 100 > /sys/devices/platform/i8042/serio0/power/latency_tolerance
```

---

### 七、扩展思考

#### 1. **为什么需要分组管理?**
- **模块化**:不同驱动可以按需添加PM功能
- **安全性**:敏感操作(如强制休眠)需要明确权限
- **性能**:避免为不支持的功能创建无用文件

#### 2. **合并组 vs 创建组的抉择**
| 场景               | 选择                | 原因                                                                 |
|--------------------|---------------------|----------------------------------------------------------------------|
| 基础PM功能         | `create_group`      | 必须存在且唯一                                                       |
| 可选功能扩展       | `merge_group`       | 可能被多个子系统扩展(如同时支持唤醒和运行时PM)                     |
| 驱动私有属性       | 单独`create_file`   | 不需要分组管理                                                       |

这段代码展现了 Linux 如何通过精巧的 sysfs 抽象,将复杂的电源管理功能以文件接口的形式暴露给用户空间,同时保持内核架构的灵活性和安全性。
 

这段代码实现了 Linux 内核中一个关键机制:**向已存在的 sysfs 属性组动态合并新属性**。以下从五个维度深入解析其设计精髓:

---

### 一、核心机制图解
```mermaid
sequenceDiagram
    participant User
    participant sysfs_merge_group
    participant kernfs
    User->>sysfs_merge_group: 调用(指定kobj和grp)
    sysfs_merge_group->>kernfs: kernfs_find_and_get(查找父目录)
    alt 父目录不存在
        kernfs-->>sysfs_merge_group: 返回-ENOENT
    else 父目录存在
        loop 遍历属性列表
            sysfs_merge_group->>kernfs: sysfs_add_file(逐个添加属性)
            alt 某个属性添加失败
                kernfs-->>sysfs_merge_group: 返回错误码
                sysfs_merge_group->>kernfs: 逆向删除已添加属性(kernfs_remove_by_name)
            end
        end
    end
    sysfs_merge_group->>kernfs: kernfs_put(释放父节点引用)
```

---

### 二、关键设计思想

#### 1. **原子性操作保证**
- **全有或全无**:要么全部属性添加成功,要么完全回滚(通过 `while (--i >= 0)` 逆向删除)
- **错误处理**:在第一个错误发生时立即终止,避免部分成功状态

#### 2. **引用计数管理**
```c
parent = kernfs_find_and_get(...);  // 增加引用
...
kernfs_put(parent);                 // 减少引用
```
- 防止目录在操作过程中被意外删除

#### 3. **分层权限控制**
- 实际文件创建由底层 `sysfs_add_file` 实现
- 当前函数专注处理属性组的逻辑关系

---

### 三、与相关函数的对比

| 函数                | 特点                                                                 | 典型应用场景                     |
|---------------------|----------------------------------------------------------------------|----------------------------------|
| `sysfs_create_group` | 创建全新的属性组目录                                                 | 设备首次注册时的基础属性         |
| `sysfs_merge_group`  | 向已有目录追加属性                                                   | 动态功能扩展(如PM子系统的扩展) |
| `sysfs_add_file`     | 添加单个属性文件                                                     | 驱动私有属性的添加               |

---

### 四、实际应用案例
#### 1. **电源管理扩展**
```c
// 当设备支持运行时PM时,动态添加相关属性
if (pm_runtime_callbacks_present(dev))
    sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group);
```

#### 2. **调试接口延迟加载**
```c
// 仅在开启调试模式时添加调试属性
#ifdef CONFIG_DEBUG_FEATURE
    sysfs_merge_group(&dev->kobj, &debug_attr_group);
#endif
```

---

### 五、安全与稳定性设计

#### 1. **错误检测**
```c
if (!parent) return -ENOENT;  // 严格检查目录存在性
```

#### 2. **权限过滤**
- 实际文件创建时会强制限制权限模式(见 `create_files()` 中的 `mode &= ...`)

#### 3. **竞争防护**
- 通过 `kernfs_find_and_get` 获取的节点引用可防止并发删除

#### 4. **内存安全**
```c
for ((i = 0, attr = grp->attrs); *attr && !error; (++i, ++attr))
```
- 自动终止于属性数组末尾(NULL 指针)

---

### 六、性能考量

#### 1. **优化点**
- **批量操作**:单次遍历完成多个属性添加
- **快速失败**:遇到错误立即终止,减少无效操作

#### 2. **潜在瓶颈**
- **线性搜索**:`kernfs_find_and_get` 需要遍历子节点查找目录
- **锁竞争**:内核全局 `kernfs_mutex` 可能成为并发瓶颈

---

### 七、扩展思考

#### 为什么需要合并机制?
1. **模块化设计**:允许不同子系统独立添加属性
   - 例如:ACPI 和 PCI 子系统可能分别向设备添加电源管理属性
2. **动态功能**:设备能力可能运行时变化(如热插拔功能)
3. **减少冗余**:避免为每个功能创建独立目录

#### 典型调用栈示例
```plaintext
device_add()
  → device_pm_add()
    → dpm_sysfs_add()
      → sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group)
        → kernfs_find_and_get("power")
        → sysfs_add_file("wakeup")
        → sysfs_add_file("wakeup_count")
```

这段代码完美体现了 Linux 内核"渐进式功能添加"的设计哲学,通过精巧的引用管理和原子性操作,实现了 sysfs 属性系统的动态扩展能力。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词