为什么Linux系统调用返回类型为"long"?

Fil*_*ves 12 c linux system-calls linux-kernel

我正在阅读Linux内核开发,第3版,以了解内核实现和设计.第5章是关于系统调用的.作者展示了使用SYSCALL_DEFINE0宏定义的系统调用声明的示例,在该特定示例中扩展为:

asmlinkage long sys_getpid(void)
Run Code Online (Sandbox Code Playgroud)

他进一步说:

[...]对于32位和64位系统之间的兼容性,定义为在用户空间中返回int的系统调用在内核中返回long.

他没有比这更深入,我不能完全理解为什么会这样.为什么使用long与32位和64位系统相关的?为什么我们不能回归平原int

Bas*_*tch 11

因为在许多64位机器(例如x86-64)上用于普通的GCC编译器sizeof(int)==4但是sizeof(void*)==8 && sizeof(long)==8; 这称为I32LP64(或仅LP64)数据模型

例如,在Linux/x86-64系统上编译并运行以下程序:

#include<stdio.h>
#include<stdint.h>
int main ()
{
  printf ("sizeof(int)=%d\n", (int) sizeof (int));
  printf ("sizeof(intptr_t)=%d\n", (int) sizeof (intptr_t));
  printf ("sizeof(short)=%d\n", (int) sizeof (short));
  printf ("sizeof(long)=%d\n", (int) sizeof (long));
  printf ("sizeof(long long)=%d\n", (int) sizeof (long long));
  printf ("sizeof(void*)=%d\n", (int) sizeof (void *));
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

在我的系统上使用Debian/Sid/x86-64(i3770k处理器,GCC 4.8 .2)编译gcc -Wall s.c -o s并运行之后:./s

sizeof(int)=4
sizeof(intptr_t)=8
sizeof(short)=2
sizeof(long)=8
sizeof(long long)=8
sizeof(void*)=8
Run Code Online (Sandbox Code Playgroud)

在使用gcc -m32 -Wall s.c -o s32和运行32位模式编译之后./s32:

sizeof(int)=4
sizeof(intptr_t)=4
sizeof(short)=2
sizeof(long)=4
sizeof(long long)=8
sizeof(void*)=4
Run Code Online (Sandbox Code Playgroud)

如果使用x32编译,我得到相同的输出gcc -mx32 -O3 -Wall s.c -o sx32!

顺便说一句,也许是更好的问题是,为什么不使用intptr_t....我不知道(可能,生活习惯的问题; 当莱纳斯刚开始编写自己的内核,在C99标准-定义<stdint.h>intptr_t-还不存在).

阅读有关ABI的更多信息,特别是仔细阅读X86-64 ABI(另请参阅x32 ABI ...)和x86调用约定的wikipage .