小议LWIP——内存对齐

每一种处理器都会有自己的内存对齐要求,这样做的目的很大程度上是为了处理器读取内存数据的效率,当然还有总线等因素的影响,具体的可以看一下为什么要内存对齐 Data alignment: Straighten up and fly right ,我觉得写得还不错。好了,废话不多说,接下来看一下LWIP在不同平台上是如何实现内存对齐的。

一. 对齐的总类及本质
在LWIP中,内存对齐分两种:

1、数据起始地址对齐,在源代码中是用宏定义实现的:

#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))

2、数据占用空间大小对齐,同样的也是使用宏定义实现:

#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1))

先不讲解为什么这么做就可以达到内存对齐的目的,我们先思考一下内存对齐的本质要求是什么,假如我们细心一点就会发现,其实对齐无非就是实现以下两点要求:
a、占用的内存大小或者地址值最后的二进制n位(根据对齐要求,如4字节对齐,n取2)必须全为0。

b、若当前占用的内存大小或者地址值最后n位不为0,则需要向上取整。比如按照4字节对齐要求(二进制最后2位必须为0),当我的变量起始地址为0x03(二进制位0b011),那么该变量的起始地址就会对齐到0x04(二进制位0b100)。

二. LWIP对齐的实现

1.、定义对齐要求

在LWIP中也是使用宏定义来设定对齐要求,用户可以在lwipopts.h中设定自己硬件平台上的对齐要求:

         /*4字节对齐*/
#define MEM_ALIGNMENT                4

2、数据占用空间大小对齐

#define LWIP_MEM_ALIGN_SIZE(size) (((size) + MEM_ALIGNMENT - 1) & ~(MEM_ALIGNMENT-1))

为啥宏定义写成是这样的呢,其实根据我刚刚说的对齐本质理解就比较简单了,假定MEM_ALIGNMENT定义为4,size取15(二进制位0b1111),那么:

a、~(MEM_ALIGNMENT-1):其实就是~(0b100-0b001)为0b1…100,目的就是当成掩码通过&运算将((size) + MEM_ALIGNMENT - 1)运算的结果后两位取0,也就是上面对齐原理的a点。
b、((size) + MEM_ALIGNMENT - 1):其实是为了满足对齐的第二点要求——向上取整。因为在第a步中,我们会二进制的最后n位取0,为了达到向上取整的效果,必须保证经过第a步的掩码操作后得出的对齐内存要大于或者等于size。根据假定size为15,经过(size) + MEM_ALIGNMENT - 1计算得到18(0b10010),最后经过第a不得掩码(0x1…100)得出16(0b10000),即15向上取整对齐后位16。

3、数据起始地址对齐

#define LWIP_MEM_ALIGN(addr) ((void *)(((mem_ptr_t)(addr) + MEM_ALIGNMENT - 1) & ~(mem_ptr_t)(MEM_ALIGNMENT-1)))

这里对齐的策略和数据占用空间大小对齐是一样的,可以依据对齐的本质理解。但是注意一个问题,在起始地址对齐时,增加了mem_ptr_t(这是移植人员定义的处理器指针类型长度,一般为u32),避免在内存最高地址处取出的对齐地址为非法地址,即地址溢出了,在这种情况,增加mem_ptr_t变量可以使得出的对齐地址重新回到0x0处。

4、保证最低的空间大小
最后一点想说的就是,在LWIP中长出现需要保证申请的空间必须在对齐的要求上达到最低的大小。比如下面这一段构造内存池的代码

static u8_t memp_memory[MEM_ALIGNMENT - 1 
#define LWIP_MEMPOOL(name,num,size,desc) + ( (num) * (MEMP_SIZE + MEMP_ALIGN_SIZE(size) ) )
#include "lwip/memp_std.h"
];

假如看不太懂先不同管其中的含义,其实就是LWIP在初始化中向内存申请空间大小为:MEM_ALIGNMENT - 1+实际需要的内存大小。所以这里就出现为什么申请要比实际需要的内存大小多出MEM_ALIGNMENT - 1个字节,看一下下面的代码:

LWIP_MEM_ALIGN(memp_memory)

原因就是在你申请完这部分空间后,系统会调用LWIP_MEM_ALIGN(数据起始地址对齐),而这个操作之前跟大家说过了,会将起始地址向上取整,那么就会有可能将所申请的空间大小减小[0,MEM_ALIGNMENT - 1],所以在实际申请的内存大小中添加MEM_ALIGNMENT - 1来保证对齐后得到的空间大小不小于实际的所需的空间大小。
这里写图片描述

其中,LWIP也有定义相应的宏定义,来申请所需要的内存大小(可以保证对齐后依旧能满足大小需求)

#define LWIP_MEM_ALIGN_BUFFER(size) (((size) + MEM_ALIGNMENT - 1))
  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值