免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1924 | 回复: 0

[应用] 小议LWIP(一)——内存对齐 [复制链接]

论坛徽章:
0
发表于 2016-11-08 13:28 |显示全部楼层
      每一种处理器都会有自己的内存对齐要求,这样做的目的很大程度上是为了处理器读取内存数据的效率,当然还有总线等因素的影响,具体的可以看一下为什么要内存对齐 Data alignment: Straighten up and fly righthttp://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,有兴趣可以看看。

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP