OpenEdv-开源电子网

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

【技术探讨】freeRTOS为什么使用全局数组做内存池

[复制链接]

1

主题

1

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2018-5-5
在线时间
4 小时
发表于 2020-5-18 10:41:51 | 显示全部楼层 |阅读模式
1金钱
freeRTOS在宿主机上使用static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];申请了一块栈中内存作为整个内存堆,这样会产生很多内存碎片等问题,为什么不直接使用malloc申请堆上内存?

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

使用道具 举报

19

主题

334

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1108
金钱
1108
注册时间
2018-11-6
在线时间
240 小时
发表于 2020-5-18 12:26:37 | 显示全部楼层
一般的嵌入式操作系统都使用全局数组做内存池(例如UCOS也使用全局数组做内存池),用链表指针将数组串起来做内存池。UCOS也是用链表指针将数组串起来做内存池。


       在ANSI C中,可以使用malloc()和free()这两个函数动态分配内存和释放内存,但是,在嵌入式操作系统中,调用malloc()和free()(不可重入函数)却是很危险的(由于多任务,有可能在某个任务执行接口函数的过程中阻塞,然后新任务再调用接口函数),因为多次调用这两个函数会把原来很大的一块连续内存逐渐分割成许多非常小而且彼此又不相邻的内存块,也就是内存碎片。由于这些内存碎片的大量存在,使得程序到后来连一段非常小的连续内存都分配不到。另外,由于内存管理算法上的原因,malloc()和free()函数的执行时间是不确定的。(申请内存时,查找合适的连续内存需要的时间不确定),对于操作系统来说,如果申请内存空间执行时间如果不可确定的话,会非常危险。
      
     在实际应用中,我们可以试着把连续的大块内存按分区来管理。每个分区中包含整数个大小相同的内存块。利用这种机制,就可以得到和释放固定大小的内存块。这样内存的申请和释放函数的执行时间就是确定的了。

      在一个操作系统中可以有多个内存分区,这样,应用程序就可以从不同的内存分区中得到不同大小的内存块。但是特定的内存块在释放时,必须重新回到它原本属于的内存分区。显然,采用这样的内存管理算法,内存碎片的问题也可以得以解决。(这种方法的内存管理可以理解为一个二维数组,比如我们定义一个二维数组为:u8 mpool[10][32]。对应的内存管理就是定义了10个内存块,每块大小是32字节。如需其他大小的内存块,还可以多定义几个其他大小。)


      总结:
              1、对于操作系统来说,如果内核某一个API函数执行时间如果不可确定的话,会非常危险。所以内核API函数编写过程中,绝对不会出现FOR循环语句或WHILE循环语句或DO WHILE循环语句,因为FOR循环语句执行时间不确定。
              2、还要考虑到任何一个函数都要支持【重入】机制。
              3、操作系统都使用全局数组做内存池,每个分区中包含整数个大小相同的内存块,利用这种机制,就可以得到和释放固定大小的内存块。这样内存的申请和释放函数的执行时间就是确定的了。
              4、自己编写申请和释放内存函数可以解决【重入】问题,调用C语言的malloc和 free 无法保证重入问题。
              5、自己编写申请和释放内存函数可以解决执行时间固定的问题,调用C语言的malloc和 free 无法保证执行时间固定的问题。




回复

使用道具 举报

22

主题

2251

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4471
金钱
4471
注册时间
2013-4-22
在线时间
335 小时
发表于 2020-5-18 15:15:50 | 显示全部楼层
你想得太多了,内存碎片一般产生都是自己分配内存产生的和编译器直接产生的没有多大关系
回复

使用道具 举报

4

主题

82

帖子

0

精华

高级会员

Rank: 4

积分
743
金钱
743
注册时间
2018-9-1
在线时间
177 小时
发表于 2020-5-18 15:43:36 | 显示全部楼层
1、不是在栈中定义的堆,这数组不是自动变量而是静态变量。
2、碎片问题,跟定义这个数组作为堆没关系。频繁动态申请/释放内存必然产生,不管你是啥系统。单片机本来内存就小,且单片机编程没有必要也不应该频繁动态申请和释放内存。官方提供的方案heap4/5支持简单的合并碎片。更复杂的合并算法或者回收算法在单片机上实现困难,也没啥必要。
3、microlib的malloc你可以使用,没说不让用。使用heap3方案就是用库函数的malloc/free,malloc用的堆和你定义的数组堆本质上一模一样,用malloc一样会有碎片问题,而且开销较大。
uevip#126.com
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-11-22 22:14

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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