![背景](https://linux22.com/image/948625/%E8%83%8C%E6%99%AF.png)
语境: 我目前正在上一门关于使用 gem5 模拟器的课程。包括我在内的很多学生都安装了 22.04,而不是文档中直接引用的 20.04。
错误:
在 22.04 中,gem5 库中的一段 c 代码示例正在从源代码重新编译。使用的构建命令是gcc -O0 --ggd3 -std=c99 -static -o a.out hello.c
(请注意,此构建命令在 20.04 中运行良好)。当在 gem5 模拟代码中运行 a.out 时,会抛出此错误build/X86/sim/syscall_desc.hh:206: fatal: Syscall 334 out of range
。
大问题: 那么在 20.04 下编译会生成与 gem5 模拟器兼容的 c 代码吗?而在 22.04 下则不会。我尝试对两者使用相同的 gcc 版本 (gcc-9),但似乎无法解决这个问题。
答案1
背景
问题是 22.04 使用 GLIBC 2.35,它增加了对可重启序列的支持。如果您有兴趣,可以在这里阅读更多有关可重启序列的信息 -https://www.efficios.com/blog/2019/02/08/linux-restartable-sequences/
可重启序列在 GLIBC 2.35 中通过在每个程序开始时向内核注册一个 rseq 结构来实现。这是通过系统调用 (syscall 334) 实现的。目前,gem5 不支持可重启序列,并且系统调用未实现(且未定义)。
解决方案
解决此问题的正确方法是恢复到 GLIBC 的早期版本(2.35 之前)。但是,如果您不打算使用可重新启动序列(大多数情况下可能都是这样),则更快的解决方案是忽略系统调用。只需在末尾添加以下行即可完成此操作gem5/src/arch/x86/linux/syscall_tbl64.cc
{ 334, "rseq", ignoreFunc }
这将声明 gem5 的系统调用,并通过忽略它来处理它。因此,rseq 结构的初始注册实际上永远不会在内核中发生,尽管在大多数情况下这可能是没问题的。
答案2
我尝试在 3 个不同的 22.04 系统上执行相同操作,但遇到了同样的问题。我认为 20.04 和 22.04 之间的 glibc 差异是导致此问题的原因。对我而言有效的解决方案是在 20.04 docker 容器中运行它。