为什么某些 Linux 系统支持 open() 系统调用,而其他系统不支持?

why is the open() syscall supported on some Linux systems and not others?

我正在内联系统调用。是的,我知道这是有问题的,但我有充分的理由。我已经相当多地追踪了我的错误,我只是想问为什么 __NR_open 在这个 arm64 Arch Linux 系统上消失了?

5.0.1-1-ARCH #1 SMP Sun Mar 10 15:08:34 MDT 2019 aarch64 GNU/Linux

同样,我的代码是内联系统调用。这种内联方法适用于另一个 X86_64 系统,实际上内联 mmap() 也适用于该系统。但是,在这个 arm64 Arch Linux 上内联 open() 失败,EFAULT.

追踪我的错误,首先,__NR_open 甚至没有在此构建环境中定义。其次,常规 open() 调用 open64() 执行 svc 指令并将 x8 设置为 # 56、__NR_open在。第三,__NR_open 通常被定义为 5,该数字已被重新用于 __NR_setxattr。这解释了 EFAULT.

基本上,open() 在此系统的用户库中被转换为 openat() 并且 __NR_open 系统调用已完全消失,由新的系统调用接管。我不明白的是 __NR_open 是在 canonical source 中为 arm64 定义的,但在这个 Arch Linux arm64 系统上没有定义。

我的错误修复很简单:改为内联 openat()。但我的问题是为什么这个被删除了,为什么这不被认为是从 Linux POV 破坏的?我在想 Linus 说 我们不会破坏用户空间! 而我 不是 从 POSIX POV 考虑这个问题。事实上,Linux 编程接口 至少没有明确地涵盖此删除。

您正在查看的文件 arch/arm64/include/asm/unistd32.h 是 arm32 兼容模式的系统调用定义。

原生 aarch64 的系统调用定义来自通用系统调用 table include/uapi/asm-generic/unistd.h,您可以看到它没有定义 __NR_open。系统调用未被删除 - 它 从未 存在于 aarch64 上。

__NR_open 没有在通用 table 中定义的原因是 openat(2) 系统调用是后来引入的,是 _NR_open 功能的严格超集,因此 new 架构端口(在引入 openat(2) 之后创建)提供该系统调用没有意义 - 它是多余的。 POSIX open() 函数由用户空间 C 库提供,调用 openat(2) 系统调用。

openat(2) 之前存在的旧架构端口 - 如 x86 和 arm32 - 必须继续包含 open(2),因为旧的 programs/library 二进制文件肯定存在于那些调用open(2) 系统调用。这个问题不适用于新的架构端口——"breaking userspace" 保证如果它昨天工作,今天也能工作,但它并没有说如果它在现有架构上工作,它可以重新编译并在某些架构上工作新架构。