关于对齐的一些问题探讨

无论是自己写代码,还是阅读一些开源的代码,总会遇到一些对齐问题,经过查阅资料和自己编程做的一些小实验,总结下关于对齐的那些事。

我个人把对齐分为字节对齐和页对齐,下面依次讨论

1.字节对齐

首先我们来思考一下CPU是如何读取数据的。

先明确一个问题,CPU不是按照字节来处理数据的,而是按照字长来处理数据的。所谓字长,就是CPU可以一次性读取的数据长度。假设CPU是32位的,那么CPU一次性就可以读取32位的数据。按照CPU的设计,读取的地址总是32的倍数开始。

字节对齐问题和CPU架构以及编译器有极大的关系。比如在x86架构中,即便是字节没有对齐,也不会出现问题,原因是x86架构的CPU支持读取奇数位地址,但是会降低程序运行的效率。用gcc编译的程序,编译器会默认4字节对齐。如果定义了一个自己没有对齐的结构体,编译器会自动帮你对齐。

但是如果是某些不支持读取奇数地址的CPU架构中,就会产生意想不到的问题。

1.1字节不对齐可能会产生错误

让我们来考察这么以下代码。

struct A{
    short i;
    short j:1;
};

struct B{
    short i;
};

struct A a;

struct B b;

如果是某些架构的CPU中,b的起始地址就会是奇数,当读取b的内容就有可能会从a.j开始读取。

当然,现在这种架构的CPU往往只会在嵌入式行业中有所应用,但是考虑到代码的可移植性,字节对齐还是很有必要做的。

1.2字节不对齐会对降低程序运行效率

考察一下结构体

struct A{
    short  i;
    int    j;
    short  k;
};
struct B{
    short  i;
    short  k;
    int    j;
};

struct A a;
struct B b;

读取a和b所用的时间是相同的吗?

答案是不相同。读取a需要CPU读取三次内存,b只需要读取两次内存就可以。如果程序中存在着大量的字节不对齐的结构体,会造成程序运行效率的下降。

2.页面对齐

页面对齐对做普通应用开发的程序员来说,是不需要操心的,但是如果涉及到高性能程序开发,比如数据转发,就需要对页面对齐有所了解。

2.1虚拟内存和内存页

关于这个问题,需要去参考计算机组成原理相关的书籍或者网上查找一些资料,这里需要知道,当CPU触发了缺页流程,是很浪费CPU性能的。这也是为什么dpdk等高性能IO开发组件需要用到巨页的原因。如果页面没有对齐,容易造成缺页。比如以下场景:

一段小于一个页面大小的连续内存,当我们需要访问这段内存的时候,CPU就需要读取两个页面,无疑增加了缺页的概率。当然,如果我们用内核的malloc函数,如果申请的内存小于一个页面大小,系统是不会给我们分配跨页的内存,但是如果我们需要开发一套内存管理程序,就需要考虑这个问题。当上层业务申请内存的时候,不能简单的返回申请内存的起始地址,而应该先判断是否跨页。

2.2如何进行页对齐

参考内核代码

向下对齐:#define alignment_down(a, size) (a & (~ (size-1)) )
向上对齐:#define alignment_up(a, size)   ((a+size-1) & (~ (size-1)))

size为页大小,这个宏要求size为2的n次幂大小,否则计算会出错

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值