2. API变更追踪:掌握如何通过内核源码的Documentation/process/deprecated.rst和API变更日志追踪驱动API的弃用与替换

内核版本迭代中,API的弃用与替换是驱动移植面临的最常见挑战。Linux内核社区通过deprecated.rst文档和API变更日志两条主线,系统性地记录每个API的生命周期变化。掌握这两类文档的定位、结构和使用方法,是精准定位驱动兼容性问题的核心技能。

核心认知:API弃用不是突然删除,而是遵循“标记弃用 → 保留兼容 → 最终移除”的渐进过程。驱动开发者需要在弃用窗口期内完成迁移,避免直接跳入移除版本。

2.1 deprecated.rst:内核API弃用的官方清单

Documentation/process/deprecated.rst 是内核社区维护的实时弃用清单,记录了所有已被标记为弃用(deprecated)的API、宏、函数和接口,并明确给出替代方案和移除计划(如有)。该文件随内核版本持续更新,是驱动移植的第一参考源。

2.1.1 文档结构与字段说明

deprecated.rst 采用统一的条目格式,每个弃用API包含以下关键字段:

字段 说明 示例
API名称 被弃用的函数/宏/结构体名称 strlcpy()
弃用版本 首次标记为弃用的内核版本 v5.10
替代API 推荐的替换接口 strscpy()
移除计划 预计移除的版本或条件 v6.3 或 “待定”
原因 弃用的技术理由 缓冲区溢出风险
实战定位:在目标内核源码根目录执行 grep -rn "deprecated" Documentation/process/deprecated.rst 可快速定位所有弃用条目。更推荐使用 scripts/get_maintainer.pl 配合 --deprecated 选项自动扫描驱动中使用的弃用API。

2.1.2 典型条目解析

以下是从 v6.1 内核 deprecated.rst 中摘录的真实条目,展示其完整结构:

strlcpy()
---------
**弃用版本**: v5.10
**替代方案**: strscpy() 或 strscpy_pad()
**移除计划**: v6.3
**原因**: strlcpy() 在源字符串长度超过目标缓冲区时不会NUL终止,
         导致潜在的缓冲区读取越界。strscpy() 保证始终NUL终止,
         并返回截断长度(负值表示截断),更安全且行为可预测。
**迁移指南**: 将 strlcpy(dst, src, size) 替换为 strscpy(dst, src, size),
             并检查返回值处理截断情况。
常见陷阱:部分API的“移除计划”标记为“待定”(TBD),表示社区尚未确定移除时间。此时驱动仍可继续使用,但应尽快迁移,因为后续版本可能随时移除。例如 kmap() 在 v5.11 标记弃用,移除计划为TBD,但在 v6.0 中已完全移除。

2.2 API变更日志:版本间的精确变更记录

除了 deprecated.rst,内核还通过API变更日志记录每个版本中API的增删改。这些日志分散在多个位置,需要开发者按图索骥。

2.2.1 变更日志的三大来源

来源 路径/命令 覆盖范围 更新频率
Documentation/ Documentation/process/deprecated.rst
Documentation/core-api/
核心API弃用与替换 随内核版本发布
Git提交日志 git log --oneline --grep="deprecated"
git log --oneline --grep="removed"
所有API变更的精确提交 实时
内核邮件列表 lore.kernel.org 搜索弃用公告 弃用决策的讨论与背景 持续

2.2.2 使用Git追踪API变更

Git提交日志是追踪API变更最精确的工具。以下命令组合可高效定位特定API的弃用与替换提交:

# 查找包含特定API的提交(以 strlcpy 为例)
git log --all --oneline --grep="strlcpy"

# 查找标记为弃用的提交
git log --all --oneline --grep="deprecated" --grep="strlcpy" --all-match

# 查看提交详情,确认替换方案
git show <commit-hash> --stat

# 查找API被移除的提交
git log --all --oneline --grep="remove" --grep="strlcpy" --all-match
效率技巧:使用 git log --oneline v5.10..v6.0 -- Documentation/process/deprecated.rst 可以查看两个版本之间 deprecated.rst 的所有变更,快速掌握该时间段内新增的弃用API。

2.3 弃用API追踪流程:从识别到替换

以下SVG流程图展示了从发现弃用API到完成替换的完整工作流:

API弃用追踪与替换流程 编译警告 / 内核告警 定位弃用API名称 查询deprecated.rst 获取替代API与迁移指南 Git提交确认移除版本 替换并回归测试 触发条件 编译时:-Wdeprecated-declarations 运行时:内核告警日志 代码审查:手动扫描 关键检查点 确认替代API的语义等价性 检查参数顺序与返回值差异

2.4 实战案例:追踪 kmap() 的弃用与替换

以 kmap() 为例,展示完整的API变更追踪过程:

  1. 编译告警触发:在 v5.11 内核上编译驱动,出现 warning: 'kmap' is deprecated。
  2. 查询 deprecated.rst:找到条目,确认替代方案为 kmap_local_page()。
  3. Git提交确认:执行 git log --oneline --grep="kmap" --grep="deprecated",找到提交 2c6b7bcd7d。
  4. 查看提交详情:git show 2c6b7bcd7d 确认弃用版本为 v5.11,移除版本为 v6.0。
  5. 迁移替换:将 kmap(page) 替换为 kmap_local_page(page),并添加对应的 kunmap_local() 调用。
迁移前后代码对比:
/* 旧代码(v5.11之前) */
void *addr = kmap(page);
/* 使用 addr */
kunmap(page);

/* 新代码(v5.11+) */
void *addr = kmap_local_page(page);
/* 使用 addr */
kunmap_local(addr);

注意:kmap_local_page() 返回的地址是CPU本地的,不能跨CPU共享,且需要成对调用 kunmap_local()。

2.5 常见API弃用模式与替换对照表

以下表格汇总了驱动移植中高频遇到的API弃用案例,覆盖内存管理、字符串操作、中断处理等核心子系统:

弃用API 弃用版本 替代API 移除版本 关键差异
strlcpy() v5.10 strscpy() v6.3 返回值语义不同;strscpy保证NUL终止
kmap() v5.11 kmap_local_page() v6.0 返回CPU本地地址,不可跨CPU共享
irq_set_affinity_hint() v5.10 irq_update_affinity_hint() v6.1 参数类型从 cpumask_var_t 改为 struct cpumask *
debugfs_create_u32() v5.12 debugfs_create_u32()(无变化) 未移除 仅标记弃用,实际未移除,但建议迁移到 debugfs_create_atomic_t()
__set_current_state() v5.14 set_current_state() v6.2 宏替换为内联函数,增加内存屏障
版本陷阱:上表中的“移除版本”基于当前最新内核(v6.6)的信息。实际移植时,请以目标内核版本的 deprecated.rst 为准,因为移除计划可能因社区讨论而调整。例如 strlcpy() 原计划 v6.0 移除,后推迟至 v6.3。

2.6 自动化工具辅助

内核社区提供了多个工具辅助API弃用检测,减少人工排查工作量:

  • coccinelle:使用语义补丁(SmPL)自动匹配并替换弃用API。内核源码 scripts/coccinelle/api/ 目录下包含大量现成规则。
  • sparse:静态分析工具,可检测部分弃用API的使用。
  • checkpatch.pl:提交检查脚本,会警告使用已弃用的API。
# 使用coccinelle自动替换strlcpy为strscpy
spatch --sp-file scripts/coccinelle/api/strlcpy.cocci \
       --dir drivers/net/ethernet/ \
       --in-place
最佳实践:在驱动移植前,先运行 make C=1 CHECK="sparse" 进行静态分析,再结合 scripts/checkpatch.pl --strict 检查弃用API使用。这两个步骤可以覆盖90%以上的API兼容性问题。

2.7 本章小结

API变更追踪是驱动移植的核心技能,需要开发者熟练掌握以下能力:

  • 文档定位:快速在 deprecated.rst 中找到目标API的弃用状态和替代方案。
  • Git回溯:通过提交日志确认API的弃用版本、移除版本和迁移细节。
  • 语义理解:理解替代API的语义差异,避免机械替换引入新bug。
  • 工具辅助:利用coccinelle、sparse等自动化工具提升效率。