Struct 结构与数组的对齐规则冲突

Struct 结构与数组的对齐规则冲突,struct,x86,memory-alignment,page-tables,Struct,X86,Memory Alignment,Page Tables,正如标题所暗示的,问题是关于Linux上x86-64中聚合类型的对齐 在我们的讲座中,教授介绍了结构(及其元素)与所附幻灯片的对齐。因此,我假设(根据维基百科和其他讲座材料),对于任何聚合类型,对齐都是根据其最大成员进行的。不幸的是,以前的一道试题似乎并非如此,题中写道: 假设每个页表[4kB,每个PTE 64b]都存储在内存中 在“自然对齐”的物理地址(即 表大小的整数倍),…” 为什么对于页表(afaik基本上是内存中8字节值的数组),对齐规则不是根据最大的元素,而是根据整个表的大小 非常感

正如标题所暗示的,问题是关于Linux上x86-64中聚合类型的对齐

在我们的讲座中,教授介绍了结构(及其元素)与所附幻灯片的对齐。因此,我假设(根据维基百科和其他讲座材料),对于任何聚合类型,对齐都是根据其最大成员进行的。不幸的是,以前的一道试题似乎并非如此,题中写道:

假设每个页表[4kB,每个PTE 64b]都存储在内存中 在“自然对齐”的物理地址(即 表大小的整数倍),…”

为什么对于页表(afaik基本上是内存中8字节值的数组),对齐规则不是根据最大的元素,而是根据整个表的大小

非常感谢您的澄清
费利克斯

为什么页面表格按大小对齐 对于虚拟地址转换过程中的给定级别,要求当前页表按其大小(以字节为单位)对齐,可加快索引操作。
CPU不需要执行实际的加法来查找下一级页表的基,它可以缩放索引,然后替换当前级基中的最低位

你可以通过几个例子来说服自己,事实确实如此。
x86也遵循这种对齐方式并不是巧合

例如,对于x86 CPU的4KB页面的4级分页,64位地址的页面目录指针字段的宽度为9位。
该表中的每个条目(PDPTE)为64位,因此页面大小为4096KiB,最后一个条目的偏移量为511*8=4088(十六进制为0xff8,因此最多只使用12位)。
页面目录指针表的地址由PML4条目给出,这些条目没有指定基的12位低位(用于其他目的),只有高位。
CPU可以简单地用PDPTE的偏移量替换PML4条目中较低的12位,因为我们已经看到它的大小为12位

这在硬件上既快又便宜(无需携带,易于使用寄存器)

假设一个国家的邮政编码由两个字段组成:城市代码(C)和区块代码(D),加在一起。
另外,假设给定城市最多可以有100个区块码,因此D为2位长。
要求城市代码在100上对齐(这意味着C的最后两位数字为零)使得C+D喜欢用D替换C的最后两位数字。 (1200+34=12 | 34)

与骨料对齐的关系 页表不被视为聚合,即8字节元素的数组。它被视为自己的一种类型,由CPU的ISA定义,必须满足使用它的CPU特定部分的要求。
PageWalker发现可以方便地根据页面表的大小对齐页面表,因此这是必需的

聚合的对齐是编译器用于分配内存中对象的一组规则,它保证满足每个元素的对齐,以便指令可以访问任何元素而不会出现对齐惩罚/错误。
加载和存储的执行单元是CPU中与页面遍历器不同的部分,因此需要不同的执行单元

您应该使用聚合对齐来了解编译器将如何对齐结构,然后检查这对于您的用例是否足够

存在例外情况 请注意,教授在解释页面表格的自然边界对齐意味着什么方面做了大量工作。

例外情况存在,如果你被告知一个数据必须在X上对齐,你可以假设其中涉及一些硬件技巧/简化,并尝试看看是哪一个,但最后你只需对齐并继续。

Margaret解释了页表的特殊性,我只回答了问题的另一部分


根据最大元素

这也不是普通结构的规则。您想要的是
max(alignof(member))
而不是
max(sizeof(member))
。因此,“根据最对齐的元素”是描述正常结构所需对齐的更好方法

e、 g.在i386系统V ABI中,
double
的sizeof=8,但alignof=4,因此
alignof(struct S1)=4
1

即使
char
成员是最后一个成员,
sizeof(struct S1)
仍然必须填充到其
alignof()
的倍数,因此所有常用的不变量都会被保留(例如
sizeof(array)=N*sizeof(struct S1)
),因此,按sizeof单步执行始终会使您到达一个足够对齐的边界,以便开始一个新的结构


脚注1:ABI是在CPU能够一次高效加载/存储8字节之前设计的。现代编译器尝试提供双精度和[u]int64t8字节对齐,例如作为结构外部的全局或局部对齐。但是ABI的结构布局规则基于任何
double
int64_t
对象的最小保证对齐来修复布局,对于这些类型,这是
alignof(t)=4

x86-64系统V对所有基元类型(包括8字节基元类型)都具有alignof(T)=sizeof(T)。这使得对任何正确对齐的
int64_t
进行原子操作成为可能,例如,简化了C++20
std::atomic_ref
的实现,从而不必检查是否有足够的对齐。()

根据最大元素。这也不是普通结构的规则。您想要的是
max(alignof(member))
而不是
max(sizeof(member))
。因此,“根据最对齐的元素”是描述正常结构所需对齐的更好方法。e、 g.在i386系统V ABI中,
double
具有si