CPU访问字节对齐

编写可移植代码,需要考虑的一个问题是如何存取不对齐的数据。

例如, 如何读取一个存储于一个不是 4 字节倍数的地址的4字节值. i386 用户常常存取不对齐数据项, 但是不是所有的体系允许这个,很多现代的CPU体系会产生异常。

 

可以采用以下的函数,进行字节对齐。

#include <asm/unaligned.h>
get_unaligned(ptr);
put_unaligned(val, ptr);

这些宏是无类型的, 并且用在每个数据项, 不管它是 1 个, 2 个, 4 个, 或者 8 个字节长.

关于对齐的另一个问题是跨平台的数据结构移植性. 同样的数据结构可能在不同的平台上编译方式不同,编译器根据各个平台不同的惯例来安排结构成员对齐。

为了编写可以跨不同CPU体系使用的数据结构,你应当一直强制自然的数据项对齐, 加上对一个特定对齐方式的标准化. 自然对齐意味着存储数据项在是数据项大小的整数倍的地址上(例如, 8-byte 项在 8 的整数倍的地址上)。

为了阻止编译器以不希望的方式调整成员变量存储位置,你应当使用填充成员来避免在数据结构中留下空洞。

 

为展示编译器如何强制对齐, dataalign 程序在源码的 misc-progs 目录中发布, 并且一个对等的 kdataalign 模块是 misc-modules 的一部分. 这是程序在几个平台上的输出以及模块在 SPARC64 的输出:

arch Align: char short int long ptr long-long u8 u16 u32 u64
i386        1    2     4   4    4   4         1  2   4   4
i686        1    2     4   4    4   4         1  2   4   4
alpha       1    2     4   8    8   8         1  2   4   8
armv4l      1    2     4   4    4   4         1  2   4   4
ia64        1    2     4   8    8   8         1  2   4   8
mips        1    2     4   4    4   8         1  2   4   8
ppc         1    2     4   4    4   8         1  2   4   8
sparc       1    2     4   4    4   8         1  2   4   8
sparc64     1    2     4   4    4   8         1  2   4   8
x86_64      1    2     4   8    8   8         1  2   4   8

kernel: arch Align: char short int long ptr long-long u8 u16 u32 u64
kernel: sparc64     1    2     4   8    8   8         1  2   4   8

有趣的是注意不是所有的平台对齐 64-位值在 64-位边界上, 因此你需要填充者成员来强制对齐和保证可移植性。

 

最后, 需要知道编译器可能自己悄悄地插入填充成员到数据结构中,用来保证每个成员是对齐的。

为了目标处理器的良好性能. 自动填充可能妨碍你的企图. 解决这个问题的方法是告诉编译器这个结构必须是"紧凑的", 不能增加填充者。

例如, 内核头文件 <linux/edd.h> 定义几个与 x86 BIOS 接口的数据结构,定义如下:

struct
{
        u16 id;
        u64 lun;
        u16 reserved1;
        u32 reserved2;
}
__attribute__ ((packed)) scsi;

在64-位CPU平台上编译这个结构时,如果没有使用__attribute__ ((packed)),在lun 成员前面,可能添加 2 个或者6 个字节进行填充。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值