金牌会员
- 积分
- 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 无法保证执行时间固定的问题。
|
|