为啥在同一个 ARM64 Linux 上调用 select 时,不同大小的 struct timeval 都可以工作?
Posted
技术标签:
【中文标题】为啥在同一个 ARM64 Linux 上调用 select 时,不同大小的 struct timeval 都可以工作?【英文标题】:Why do both struct timeval with different sizes work when calling select on the same ARM64 Linux?为什么在同一个 ARM64 Linux 上调用 select 时,不同大小的 struct timeval 都可以工作? 【发布时间】:2020-11-20 00:14:30 【问题描述】:我使用 ARMv7 和 ARMv8 工具链来编译相同的 .c 文件,如下所示。然后我使用 QEMU 在 ARM64 Linux 上运行了两个生成的程序(select32
和 select64
)。
#include <sys/select.h>
#include <stdio.h>
int main()
struct timeval t = 10, 999999;
printf("sizeof timeval is %d, sizeof(tv_sec) is %d, sizeof(tv_usec) is %d\nstart select()\n",
(int) sizeof(struct timeval), (int)sizeof(t.tv_sec), (int)sizeof(t.tv_usec));
select(0,0,0,0, &t);
printf("select() ends\n");
我发现两个程序在start select()
和select() ends
之间都睡了大约10秒
/ # ./select64
sizeof timeval is 16, sizeof(tv_sec) is 8, sizeof(tv_usec) is 8
start select()
select() ends
/ # ./select32
sizeof timeval is 8, sizeof(tv_sec) is 4, sizeof(tv_usec) is 4
start select()
select() ends
为什么 32 位应用程序也休眠了 10 秒,尽管(我认为)它通过了内核没有预料到的 struct timeval 形式?是内核中的某些代码,还是 C 库中的某些代码,发现了一些奇怪的东西然后转换了结构?
【问题讨论】:
【参考方案1】:当你用 32 位工具链编译时,struct timeval
的成员是 32 位的,当你用 64 位工具链编译时,它们是 64 位的。这意味着您提供的值会被编译器自动转换为适当的类型,并且您传递给它的数据大小合适。
如果使用的类型较大(如long
,这可能是所使用的,则在结构初始化程序中使用它们时,C 编译器会自动将您提供的 int
类型的值转换为适当的类型在引擎盖下)。
32 位和 64 位程序的系统调用不同,所以在这种情况下,当您调用 select
时,您实际上是在调用两个不同的系统调用,其中一个可能是 32 位 EABI,另一个可能是, 64 位。
【讨论】:
【参考方案2】:内核区分 32 位和 64 位系统调用。 32 位 select
传递 old_timeval32
或 compat_timeval
结构,而 64 位 select
传递 timeval
结构类型。由于Year 2038 problem,不推荐使用 32 位。
与timespec
类似:32位pselect
传递timespec
结构,而64位pselect
传递timespec64
结构。实现之间的名称不同,例如,compat_timespec
用于 32 位,timespec
用于 64 位。
这里有一些来自 Raspberry Pi OS 中使用的 linux 内核的代码:compat.c
中有明确的转换例程来在两种类型之间复制数据:
static int compat_put_timeval(struct compat_timeval __user *o,
struct timeval *i)
return (put_user(i->tv_sec, &o->tv_sec) ||
put_user(i->tv_usec, &o->tv_usec)) ? -EFAULT : 0;
【讨论】:
以上是关于为啥在同一个 ARM64 Linux 上调用 select 时,不同大小的 struct timeval 都可以工作?的主要内容,如果未能解决你的问题,请参考以下文章
如果节点这样做,为啥 verdaccio 不支持 arm 处理器
Linux-我可以在aarch64体系结构上运行arm64二进制文件吗?