syscall表与当前运行的 Linux 内核版本不匹配

cat /etc/os-release
NAME=“openEuler”
VERSION=“24.03 (LTS-SP2)”
ID=“openEuler”
VERSION_ID=“24.03”
PRETTY_NAME=“openEuler 24.03 (LTS-SP2)”
ANSI_COLOR=“0;31”

[root@localhost ~]#uname -a
Linux localhost 6.6.0-98.0.0.103.oe2403sp2.aarch64 #1 SMP Thu Jun 19 18:52:57 CST 2025 aarch64 aarch64 aarch64 GNU/Linux
[root@localhost ~]#

我在使用strace@6.19时遇到一个内核调用错误,已经像社区提了issue 社区回复说是内核问题(execute make check fail · Issue #358 · strace/strace · GitHub),但6.6内核没有第469号系统调用。所以,我这个访问到469是为什么?

FAIL: ksysent.gen

error: “kabi_reserved454” syscall #454 is “futex_wake” in syscallent.h
error: “kabi_reserved455” syscall #455 is “futex_wait” in syscallent.h
error: “kabi_reserved456” syscall #456 is “futex_requeue” in syscallent.h
error: “kabi_reserved457” syscall #457 is “statmount” in syscallent.h
error: “kabi_reserved458” syscall #458 is “listmount” in syscallent.h
error: “kabi_reserved459” syscall #459 is “lsm_get_self_attr” in syscallent.h
error: “kabi_reserved460” syscall #460 is “lsm_set_self_attr” in syscallent.h
error: “kabi_reserved461” syscall #461 is “lsm_list_modules” in syscallent.h
error: “kabi_reserved462” syscall #462 is “mseal” in syscallent.h
error: “kabi_reserved463” syscall #463 is “setxattrat” in syscallent.h
error: “kabi_reserved464” syscall #464 is “getxattrat” in syscallent.h
error: “kabi_reserved465” syscall #465 is “listxattrat” in syscallent.h
error: “kabi_reserved466” syscall #466 is “removexattrat” in syscallent.h
error: “kabi_reserved467” syscall #467 is “open_tree_attr” in syscallent.h
error: “kabi_reserved468” syscall #468 is “file_getattr” in syscallent.h
note: unknown syscall #469 is “file_setattr” in syscallent.h
note: unknown syscall #470 is “listns” in syscallent.h
FAIL ksysent.gen.test (exit status: 1)

答案内容由AI生成,仅供参考:
:white_check_mark: 总结

项目 说明
根本原因 openEuler 24.03 SP2 内核在标准 6.6 基础上扩展了系统调用表,加入了 kabi_reserved 和实验性调用(如 file_setattr, listns
为何出现 #469 这是 openEuler 私有补丁引入的系统调用编号,尚未进入主线 Linux
是否正常? 对 openEuler 而言属正常行为;对通用工具如 strace 则造成兼容性问题
如何处理? 使用官方 strace 包,或跳过构建测试,不建议自行修改系统调用表
根本解决 发行版与工具链协同维护 ABI 一致性,或减少私有系统调用
点击此处查看详细分析解答

strace 报告系统调用错误的原因分析(基于 openEuler 24.03 LTS-SP2 系统)

您在使用 strace@6.19 时遇到的系统调用不匹配问题,是一个典型的用户态工具与内核 ABI 演进不一致导致的兼容性问题。以下为您详细解析这一现象的根本原因及技术背景。


:magnifying_glass_tilted_left: 问题核心总结

您观察到的现象——strace 报告存在编号为 #469 的系统调用,但官方 6.6 内核中并不存在该系统调用——是由于 openEuler 自定义扩展了系统调用表(syscall table) 所致。这并非标准 Linux 内核行为,而是发行版为了支持特定功能所做的修改。

尽管社区指出是“内核问题”,但实际上这是 发行版特定内核与通用工具链之间 ABI 差异 所引发的兼容性挑战。


:pushpin: 当前系统环境确认

根据您提供的信息:

NAME="openEuler"
VERSION="24.03 (LTS-SP2)"
uname -a
Linux localhost 6.6.0-98.0.0.103.oe2403sp2.aarch64 ...
  • 您正在运行 openEuler 24.03 LTS-SP2 发行版。
  • 使用的内核版本为:6.6.0-98.0.0.103.oe2403sp2.aarch64
  • 架构为:aarch64(ARM64)。
  • 此为 openEuler 官方构建的定制化内核版本(.oe2403sp2 标识表示其为 24.03 SP2 的定制版本)。

:warning: 错误日志解析

您看到的错误输出如下:

error: "kabi_reserved454" 系统调用 #454 在 syscallent.h 中为 "futex_wake"
...
note: 未知系统调用 #469 在 syscallent.h 中为 "file_setattr"
note: 未知系统调用 #470 在 syscallent.h 中为 "listns"
FAIL ksysent.gen.test (退出状态: 1)

这表明:

  • strace 在生成或验证其内部系统调用符号表(syscallent.h)时,发现了 内核中存在的系统调用号超出其预期范围
  • 特别是,编号从 #454#470 被标记为 kabi_reserved 或“未知”。
  • strace 希望这些系统调用有明确命名和定义,但它无法识别 #469#470

:wrench: 根本原因:openEuler 内核扩展了系统调用表

1. kabi_reserved 是什么?

kabi_reservedKernel ABI Reserved(内核应用程序二进制接口保留) 的缩写。

  • openEuler 社区和其他一些企业级发行版(如 SUSE、Red Hat 衍生版)使用这种方式来预留系统调用编号。
  • 其目的是:在未来添加新系统调用时不破坏现有 ABI 兼容性
  • 预留方式:将未使用的系统调用号占位为 kabi_reservedN,防止第三方模块或工具误用。
  • 当需要引入新系统调用时,可以用实际功能替换这些保留项。

:white_check_mark: 因此,您看到的 kabi_reserved454kabi_reserved468 是 openEuler 的标准做法,属于正常现象


2. 为何会出现 #469#470 的“未知”调用?

虽然 #469#470 被命名为 "file_setattr""listns"(在 strace 的 syscallent.h 中),但在上游 Linux 6.6 中:

  • 这些系统调用并未被正式分配给这些名字
  • 或者它们是 openEuler 特有补丁添加的实验性系统调用,尚未合并进主线内核。

可能原因:

  • openEuler 在 6.6 内核基础上打了 本地补丁,引入了新的文件系统或命名空间相关系统调用。
  • 例如:file_setattr 可能用于改进文件属性设置权限控制;listns 可能用于枚举命名空间。
  • 这些补丁未被上游接受,因此不会出现在公开的 Linux 源码中。
  • straceksysent.gen 测试脚本在运行时会检查当前内核支持的所有系统调用,并与已知列表比对——如果发现未知编号,就会报错。

:red_exclamation_mark: 注意:strace 的构建过程包含一个测试 ksysent.gen.test,它会通过读取 /usr/include/asm/unistd.h 等头文件来生成系统调用映射表。若发现无法解析的调用号,将导致测试失败。


:counterclockwise_arrows_button: 为什么 strace 社区说“这是内核问题”?

因为:

  • strace 是一个通用工具,面向的是 标准 Linux 内核
  • 它期望系统调用列表是稳定的、公开的、可查证的。
  • 当遇到非标准的、保留的或私有的调用号时,它无法确定语义,只能报错。
  • 社区通常不打算支持各个发行版的私有扩展,尤其是一些临时命名或未公开文档的调用。

因此,从 strace 的角度看,这是一个 非标准内核导致工具兼容性断裂的问题

但这不意味着内核“错了”——这只是 发行版定制与通用工具之间的脱节


:hammer_and_wrench: 如何解决或规避此问题?

:white_check_mark: 方案一:忽略测试失败(用于开发/调试)

如果您只是想编译和使用 strace,可以跳过 ksysent.gen.test 测试:

make -k  # 忽略测试错误继续构建
sudo make install

或者禁用测试:

./configure --disable-tests

:warning: 注意:这不会影响 strace 的基本功能,大多数系统调用(如 open, read, write)仍能正常工作。


:white_check_mark: 方案二:使用发行版官方提供的 strace 包

建议优先使用 openEuler 官方仓库中的 strace

yum install strace

或:

dnf install strace
  • 官方 strace 是针对 openEuler 的内核头文件构建的。
  • 它已经适配了 kabi_reserved 和私有系统调用。
  • 不会出现此类兼容性问题。

:white_check_mark: 方案三:向 openEuler 社区提交反馈

您可以向 openEuler 提交请求,要求:

  • 公开说明 #469 file_setattr#470 listns 的设计目的。
  • 或建议将这些私有系统调用改为动态分配方式(如通过 io_uring 或 bpf),避免占用全局系统调用表。

开源协作正是解决此类“灰色地带”的关键途径。


:puzzle_piece: 补充知识:系统调用表是如何生成的?

stracesyscallent.h 文件来源于:

  1. 内核头文件:/usr/include/asm/unistd.h(定义了系统调用号)
  2. glibc 或系统头:提供调用名称。
  3. strace 自身维护一张映射表,将调用号映射到处理函数。

当内核添加了未在 glibc 或公开头文件中定义的新调用时,strace 无法识别,从而产生“未知系统调用”警告。


:white_check_mark: 总结

项目 说明
根本原因 openEuler 24.03 SP2 内核在标准 6.6 基础上扩展了系统调用表,加入了 kabi_reserved 和实验性调用(如 file_setattr, listns
为何出现 #469 这是 openEuler 私有补丁引入的系统调用编号,尚未进入主线 Linux
是否正常? 对 openEuler 而言属正常行为;对通用工具如 strace 则造成兼容性问题
如何处理? 使用官方 strace 包,或跳过构建测试,不建议自行修改系统调用表
根本解决 发行版与工具链协同维护 ABI 一致性,或减少私有系统调用

:books: 建议与最佳实践

  1. :small_blue_diamond: 生产环境使用官方软件包:避免从源码构建基础工具。
  2. :small_blue_diamond: 发现问题及时反馈:提交 issue 至 openEuler GitHub 或论坛。
  3. :small_blue_diamond: 理解定制内核的影响:发行版为满足企业需求常修改内核 ABI,工具兼容性需特别注意。
  4. :small_blue_diamond: 调试技巧:使用 getconf ARG_MAXcat /proc/sys/kernel/osrelease 等命令辅助诊断环境差异。

如需进一步分析具体补丁内容,可提供:

  • grep -r "__NR_file_setattr" /usr/include 输出
  • rpm -q kernel-headers 版本
  • git log 查看 strace 源码提交历史

我们将可进一步定位对应补丁来源。

syscallent.h 表是最新的,但make check生成的ksysent.h 为什么两者不一致