- 论坛徽章:
- 0
|
每一种处理器都会有自己的内存对齐要求,这样做的目的很大程度上是为了处理器读取内存数据的效率,当然还有总线等因素的影响,具体的可以看一下为什么要内存对齐 Data alignment: Straighten up and fly right【http://blog.csdn.net/lgouc/article/details/8235471】,我觉得写得还不错。好了,废话不多说,接下来看一下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),最后经过第上步的掩码(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))
PS:由于本人水平有限,可能存在一些误区,请各位多指教。这是我发在SCDN的博客原文http://blog.csdn.net/u012866052/article/details/53008721,有兴趣可以看看。
|
|