OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5336|回复: 2

FreeRTOS heap_1内存分配问题

[复制链接]

7

主题

13

帖子

0

精华

初级会员

Rank: 2

积分
89
金钱
89
注册时间
2015-10-2
在线时间
7 小时
发表于 2018-3-24 12:23:51 | 显示全部楼层 |阅读模式
我觉得这个分配内存算法还有点瑕疵。不知个人理解的对否,请各位大神给予指正。

获取内存函数如下:
void *pvPortMalloc( size_t xWantedSize )
{
void *pvReturn = NULL;
static uint8_t *pucAlignedHeap = NULL;
...//省略
        {
                if( pucAlignedHeap == NULL )
                {
                        /* Ensure the heap starts on a correctly aligned boundary. */
                        pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
                }
...//省略
}
这个pucAligedHeap这个是我想讨论的地方:
pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
当然大家都知道这条语句的目的是为了对齐地址。
比如:ucHeap被编译器分配的地址:0x20005001 , portBYTE_ALIGNMENT = 4 , 则portBYTE_ALIGNMENT_MASK = 0x03
则经过这条语句执行可得到:pucAlignedHeap = (0x20005001 + 4) & (0xffff fff8) = 0x20005005 & 0xffff fffc = 0x20005004
那么这个时候得出的就是首次分配内存时候应该返回的内存地址。也相当于 从数组ucHeap开头处向右偏移3个地址以对齐。这样理解貌似没有问题。
但是,如果ucHeap被编译器分配的地址为:0x20005004 , portBYTE_ALIGNMENT = 4 , 则portBYTE_ALIGNMENT_MASK = 0x03
则经过这条语句执行可得到:pucAlignedHeap = (0x20005004 + 4) & (0xffff fff8) = 0x20005004 & 0xffff fffc = 0x20005008。这样岂不是浪费了几个字节的内存。
就是说如果本来地址就是按照portBYTE_ALIGNMENT 对齐,就浪费了内存了。大神们,你觉得呢?是不是可以这么理解?







正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
发表于 2018-3-24 13:10:45 来自手机 | 显示全部楼层
回复 支持 反对

使用道具 举报

22

主题

203

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
378
金钱
378
注册时间
2017-11-29
在线时间
135 小时
发表于 2018-4-23 14:58:40 | 显示全部楼层
这两天跟着左工的视频把heap_1到Heap_4的源码过了一遍,我试着解答下你的问题,不对的地方请指出来。
如你假设:ucHeap被编译器分配的地址为0x20005001,采用4字节对齐,即 portBYTE_ALIGNMENT = 4 和portBYTE_ALIGNMENT_MASK为0x0003。根据公式正确的计算应该是pucAlignedHeap =(0x20005001+3)& (0xFFFFFFFC)=0x20005004;如果ucHeap被编译器分配的地址如你假设正好是0x20005004,根据公式我们计算下(如你假设的仍用4字节对齐)pucAlignedHeap =(0x20005004+3)& (0xFFFFFFFC)=0x20005004,看见了吧?结果是0x20005004。

所以你使用公式的时候有两个地方理解不对:一个是数组是第一个元素是从0开始的,所以被编译器分配的初始地址要加3而不是4;另一个就是既然你举例是4字节对齐,那么 portBYTE_ALIGNMENT_MASK就应该是0x0003,取反再强制类型转换不就是0xFFFF FFFC吗?所以如果被编译器分配的内存池起始地址如果正好是字节对齐的,那就直接用,没有浪费的问题。




回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 23:14

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表