关于影子变量 【ChatGPT】

简介: 关于影子变量 【ChatGPT】

关于影子变量

影子变量是一种简单的方法,用于让 livepatch 模块将额外的“影子”数据与现有数据结构关联起来。影子数据是单独分配的,而父数据结构保持不变。本文档描述的影子变量 API 用于为它们的父对象分配/添加和移除/释放影子变量。

该实现引入了一个全局的内核哈希表,将父对象的指针和影子数据的数值标识符关联起来。数值标识符是一个简单的枚举,可用于描述影子变量的版本、类别或类型等。具体来说,父指针充当哈希表键,而数值标识符随后用于过滤哈希表查询。多个影子变量可以附加到同一个父对象上,但它们的数值标识符可以区分它们。

1. 简要 API 摘要

(请参阅 livepatch/shadow.c 中的完整 API 使用文档注释。)

一个哈希表引用了所有影子变量。这些引用通过 <obj, id> 对存储和检索。

  • klp_shadow 变量数据结构封装了跟踪元数据和影子数据:
  • 元数据
  • obj - 指向父对象的指针
  • id - 数据标识符
  • data[] - 用于存储影子数据

需要注意的是,klp_shadow_alloc() 和 klp_shadow_get_or_alloc() 默认会将变量清零。它们还允许在需要非零值时调用自定义构造函数。调用者应提供所需的互斥操作。

需要注意的是,构造函数是在 klp_shadow_lock 自旋锁下调用的。这允许执行只能在分配新变量时执行一次的操作。

  • klp_shadow_get() - 检索影子变量数据指针 - 在哈希表中搜索 <obj, id> 对
  • klp_shadow_alloc() - 分配并添加新的影子变量 - 在哈希表中搜索 <obj, id> 对
  • 如果存在
  • 发出警告并返回 NULL
  • 如果 <obj, id> 不存在
  • 分配一个新的影子变量
  • 使用自定义构造函数和数据初始化变量(如果提供)
  • 将 <obj, id> 添加到全局哈希表中
  • klp_shadow_get_or_alloc() - 获取现有或分配新的影子变量 - 在哈希表中搜索 <obj, id> 对
  • 如果存在
  • 返回现有的影子变量
  • 如果 <obj, id> 不存在
  • 分配一个新的影子变量
  • 使用自定义构造函数和数据初始化变量(如果提供)
  • 将 <obj, id> 对添加到全局哈希表中
  • klp_shadow_free() - 分离并释放 <obj, id> 影子变量 - 从全局哈希表中查找并移除 <obj, id> 引用
  • 如果找到
  • 如果已定义,调用析构函数
  • 释放影子变量
  • klp_shadow_free_all() - 分离并释放所有 <, id> 影子变量 - 从全局哈希表中查找并移除任何 <, id> 引用
  • 如果找到
  • 如果已定义,调用析构函数
  • 释放影子变量

2. 使用案例

(请参阅 samples/livepatch/ 中的示例影子变量 livepatch 模块,以获取完整的工作演示。)

对于以下使用案例示例,请考虑提交 1d147bfa6429("mac80211: fix AP powersave TX vs. wakeup race"),该提交在 net/mac80211/sta_info.h :: struct sta_info 中添加了一个自旋锁。每个使用案例示例都可以视为此修复的独立 livepatch 实现。

匹配父对象的生命周期

如果父数据结构经常被创建和销毁,将它们的影子变量生命周期与相同的分配和释放函数对齐可能是最简单的方法。在这种情况下,通常会分配、初始化父数据结构,然后以某种方式注册它们。影子变量的分配和设置可以被视为父对象的初始化的一部分,并且应在父对象“上线”之前完成(即,为此 <obj, id> 对进行任何影子变量 get-API 请求)。

对于提交 1d147bfa6429,当分配父 sta_info 结构时,分配 ps_lock 指针的影子副本,然后对其进行初始化:

#define PS_LOCK 1
struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
const u8 *addr, gfp_t gfp)
{
struct sta_info *sta;
spinlock_t *ps_lock;
/* 创建父结构 */
      sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp);
/* 附加相应的影子变量,然后对其进行初始化 */
      ps_lock = klp_shadow_alloc(sta, PS_LOCK, sizeof(*ps_lock), gfp,
NULL, NULL);
if (!ps_lock)
goto shadow_fail;
      spin_lock_init(ps_lock);
      ...

在需要 ps_lock 时,查询影子变量 API 以检索特定 struct sta_info 的一个:

void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
{
spinlock_t *ps_lock;
/* 与 ieee80211_tx_h_unicast_ps_buf 同步 */
      ps_lock = klp_shadow_get(sta, PS_LOCK);
if (ps_lock)
              spin_lock(ps_lock);
      ...

当父 sta_info 结构被释放时,首先释放影子变量:

void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
{
      klp_shadow_free(sta, PS_LOCK, NULL);
      kfree(sta);
      ...

运行中的父对象

有时,可能不方便或不可能在运行中的父对象旁边分配影子变量。或者 livepatch 修复可能仅需要对父对象实例的子集使用影子变量。在这些情况下,可以使用 klp_shadow_get_or_alloc() 调用将影子变量附加到已在运行中的父对象上。

对于提交 1d147bfa6429,一个很好的分配影子自旋锁的位置是在 ieee80211_sta_ps_deliver_wakeup() 内部:

int ps_lock_shadow_ctor(void *obj, void *shadow_data, void *ctor_data)
{
spinlock_t *lock = shadow_data;
      spin_lock_init(lock);
return 0;
}
#define PS_LOCK 1
void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
{
spinlock_t *ps_lock;
/* 与 ieee80211_tx_h_unicast_ps_buf 同步 */
      ps_lock = klp_shadow_get_or_alloc(sta, PS_LOCK,
sizeof(*ps_lock), GFP_ATOMIC,
                      ps_lock_shadow_ctor, NULL);
if (ps_lock)
              spin_lock(ps_lock);
      ...

这种用法将仅在需要时创建一个影子变量,否则将使用已为此 <obj, id> 对创建的变量。

与之前的使用案例类似,影子自旋锁需要进行清理。影子变量可以在其父对象被释放之前释放,或者甚至在不再需要影子变量本身时释放。

其他使用案例

影子变量还可以用作指示数据结构是由新的、经过 livepatch 的代码分配的标志。在这种情况下,影子变量持有的数据值并不重要,其存在表明如何处理父对象。

3. 参考资料

  • livepatch 实现基于 kpatch 版本的影子变量。
  • Kritis Makris, Kyung Dong Ryu 于 2007 年提出了一种称为“影子数据结构”的数据类型更新技术。
相关文章
|
4月前
|
机器学习/深度学习 编解码 并行计算
【FasterVIT】试图从FasterVIT网络结构中窥探出一些有用的信息
【FasterVIT】试图从FasterVIT网络结构中窥探出一些有用的信息
65 0
【FasterVIT】试图从FasterVIT网络结构中窥探出一些有用的信息
|
4月前
|
自然语言处理 搜索推荐 自动驾驶
【ChatGPT 指令大全】怎么利用ChatGPT写报告
【ChatGPT 指令大全】怎么利用ChatGPT写报告
90 0
|
19天前
|
Rust 安全 Java
神秘编程世界惊现独特规则,Rust 核心特性究竟隐藏着怎样的秘密?快来一探究竟!
【8月更文挑战第31天】在编程领域,Rust 以所有权、借用和生命周期等核心特性著称,提供强大的内存安全保障。所有权确保每个值有唯一所有者并自动管理内存,避免手动管理内存带来的问题。借用则允许临时访问值而不转移所有权,确保内存安全访问。生命周期机制在编译时保证引用的有效性,无需运行时检查。通过对比 Rust 与 C/C++ 的示例,可以更清晰地理解这些特性带来的优势。
25 1
|
2月前
|
人工智能 SEO
Sora信息问题之sora使用过程中的注意事项如何解决
Sora信息问题之sora使用过程中的注意事项如何解决
38 0
|
3月前
|
传感器 存储 编解码
数码相机背后的像素秘密:静态与动态的真相
这篇文章探讨了数码摄影中“动态像素”和“静态像素”的概念。像素是图像质量的关键因素,而CCD或CMOS传感器负责将光信号转化为数字图像。RGB差值补偿算法用于恢复色彩,但牺牲了部分分辨率。所谓“动态像素”更多是营销术语,而非技术标准,它反映了拍照和录像时因硬件限制和处理需求不同而产生的差异。随着技术进步,硬件编码器的引入已显著提升视频处理能力,使得高清摄影和视频录制变得更加普遍。理解这些原理有助于消费者做出更明智的设备选择。
|
4月前
|
存储 C# 容器
救命!C变量定义的秘密居然被我发现了!
救命!C变量定义的秘密居然被我发现了!
27 2
|
4月前
|
缓存 自然语言处理 前端开发
探秘闭包:隐藏在函数背后的小秘密(上)
探秘闭包:隐藏在函数背后的小秘密(上)
探秘闭包:隐藏在函数背后的小秘密(上)
|
4月前
|
存储 缓存 Java
探秘闭包:隐藏在函数背后的小秘密(下)
探秘闭包:隐藏在函数背后的小秘密(下)
探秘闭包:隐藏在函数背后的小秘密(下)
|
10月前
|
机器学习/深度学习 存储 人工智能
【网安AIGC专题11.8】论文15 ChatGPT在软件工程中的全面作用:程序语法(AST生成、表达式匹配) 静态行为、动态分析(数据依赖和污点分析、指针分析) 提示设计(角色提示、指令提示)
【网安AIGC专题11.8】论文15 ChatGPT在软件工程中的全面作用:程序语法(AST生成、表达式匹配) 静态行为、动态分析(数据依赖和污点分析、指针分析) 提示设计(角色提示、指令提示)
102 0
|
10月前
|
机器学习/深度学习 自然语言处理 算法
【网安AIGC专题10.25】论文7:Chatgpt/CodeX引入会话式 APR 范例+利用验证反馈+LLM 长期上下文窗口:更智能的反馈机制、更有效的信息合并策略、更复杂的模型结构、鼓励生成多样性
【网安AIGC专题10.25】论文7:Chatgpt/CodeX引入会话式 APR 范例+利用验证反馈+LLM 长期上下文窗口:更智能的反馈机制、更有效的信息合并策略、更复杂的模型结构、鼓励生成多样性
127 0