9

许多 linux/x86-64 系统调用接受指向结构的指针作为参数。

例如第二个参数stat(2)struct stat*...

   struct stat {
       dev_t     st_dev;     /* ID of device containing file */
       ino_t     st_ino;     /* inode number */
       mode_t    st_mode;    /* protection */
       nlink_t   st_nlink;   /* number of hard links */
       uid_t     st_uid;     /* user ID of owner */
       gid_t     st_gid;     /* group ID of owner */
       dev_t     st_rdev;    /* device ID (if special file) */
       off_t     st_size;    /* total size, in bytes */
       blksize_t st_blksize; /* blocksize for file system I/O */
       blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
       time_t    st_atime;   /* time of last access */
       time_t    st_mtime;   /* time of last modification */
       time_t    st_ctime;   /* time of last status change */
   };

这意味着如果你想从纯汇编中调用系统调用,那么你必须知道每种类型有多大的规则,以及成员之间是否有任何用于对齐目的的填充,等等。

C 标准是否将其保留为(编译器)实现定义,还是可以从标准中确定(假设原始类型大小已知)?

如果它保持打开状态,内核或 x86-64 架构是否以任何方式定义它?还是只是内核碰巧用哪个编译器编译的问题?

(给定结构的某些成员,我需要计算该成员相对于结构地址的起始偏移量)

4

2 回答 2

14

结构的布局不是在 C 标准中定义的,而是在 ABI 定义中定义的,在您的情况下是 System V AMD64 ABI。也就是说,通常布局依赖于操作系统,并且所有针对该操作系统的编译器都必须符合 ABI(尽管如果您知道自己在做什么,大多数编译器都可以选择生成不同的布局)。ABI 还定义了如何将参数传递给函数、如何返回值、必须在调用之间保留哪些寄存器等等。

您需要的 ABI 定义应在http://www.x86-64.org/上提供(似乎已关闭)

于 2013-01-16T09:58:47.377 回答
0

在 Linux/x86-64 下:

一个字节是 8 位。大小和内存地址以 1 字节为单位。

原始类型

原始类型的对齐等于它们的大小:

原始类型大小(和对齐方式)是:

bool 1
char 1
short 2
int 4
long 8
long long 8
__int128 16
void* 8
float 4
double 8
long double 16
__float128 16
__m64 8
__m128 16

结构体、联合体和数组

  • 结构(和联合)对齐是其任何组件的最大对齐。

  • 每个结构成员都分配给具有适当对齐方式的最低可用偏移量。

  • 结构的大小向上舍入到最接近的对齐倍数。

  • 结构和联合对象可能需要填充以满足大小和对齐约束。任何填充的内容都是未定义的。

  • 小于 16 字节的数组具有其元素类型的对齐方式。

  • 16 字节或更长的数组具有 (a) 16 中较高的对齐;(b) 其元素类型的对齐方式。

于 2013-01-16T13:43:38.687 回答