基本原理是湖肚搜寻, 急速malloc, 找出两个malloc(n)成功, malloc(n+1)失败的边线
假如堆内部空间不已连续, 回到的假如是最小已连续内部空间.
流程如下表所示, get_free_mem()中初始化__get_free_mem()时选定上上界.
主要问题有两个, 一是在64k范围时要递归十几次, 4G范围时得递归30多次. 假如初始化边线比较深总担心要爆栈, 得改成非递归的;
二是stm32的syscall.c里的_sbrk()实现是判断heap_end加上incr是否超过asm(“SP”),
其中heap_end是静态变量, 第一次初始化时取_end的值. 这样有个问题是把bss段和当前未用的栈内部空间都给算到堆内部空间了, 似乎不太合适. 是否假如跳过bss段, 以及把整个栈内部空间都去掉?
实测: 在PC上用32位gcc编译, 结果是1.8G左右的缓存. 在512M缓存的树莓派上是345M左右, 都还算合理.
在48k ram的stm32f103rct6上则比较有趣, make完size的结果是.data+.bss一共10256字节,
49152-10256=38896, 再去掉已用掉的栈内部空间, 假如是38k不到的样子. 但是get_free_mem的结果总是32768.
假如先malloc(16000), get_free_mem的结果就变成了16384. 继续malloc, 结果逐渐减小为8192, 4096. 估计是arm-none-eabi-gcc的malloc内部实现上做了限制, 只取需用堆内部空间里最小的2的整数次幂.
假如先这样:
这样可以成功分配到46300字节, 看来确实是把bss都算进来了. 然后, 果然hardfault了…
上面两点有空再改吧.
—————-更新——————–
上面的说法有误,arm-none-eabi-size -A main_rom.elf的结果, .bss是1860, ._user_heap_stack是8192. 而arm-none-eabi-size -B main_rom.elf的结果, bss是10052,假如是把上面两者都算作bss了。
_user_heap_stack这部分作为堆内部空间是没有问题的,它假如只是在编译时起到检查静态内部空间是否越界的作用。
——————–再更新———————
非递归版本的__get_free_mem表达式如下表所示… 脑子短路了,这个感觉比递归的还简单…