嵌入式C语言的堆栈管理怎样实现( 二 )


C语言的堆管理,其实就是这个流程。一般C标准库会有专门的内存管理器,比如glibc的ptmalloc管理器,相当于小卖部,我们每次使用malloc/free申请内存,都是ptmalloc管理的,ptmalloc会管理不同大小的内存块,相似的内存块通过一个链表维护、包括已使用的、未使用的(free list)。对于小块内存的申请,申请与释放,内存是不会直接归还操作系统的,都是放到这里维护。
如果你申请的内存太大,超过某个阈值,比如128KB(这些可以通过内核选项配置),ptmalloc没有这么大的空间给你,这时候我们就要通过系统调用(brk或mmap)向操作系统申请空间,操作系统会在BSS段的后面,堆的后面,我们知道有大量的未使用空间,批准一块给你用,这样,你对这块内存就有了读写权限。这就跟房地产开发商一样,郊区有大量的空地,但是你没权限,政府在管理着,想用就要申请(通过系统调用),比如linux内核和MMU的最大作用就是内存管理、读写权限管理。硬件与软件结合,对内存进行管理,比裸机纯粹的“小卖部”复杂点

一般来讲,不同的操作系统,对内存管理可能不同,比如linux,虽然在C库中已经定义了malloc/free函数给用户使用,但是malloc/free实现机制上,跟linux的内存管理相结合,通过系统调用,然后由内核分配内存,自己也实现了堆管理,适应不同大小的内存分配。
而对于嵌入式裸机系统,一般我们直接操作的是物理内存,使用malloc/free来申请内存,缺点是容易引起内存碎片,系统运行一段时间就有可能因为申请不到合适的内存而宕机。所以在嵌入式逻辑系统中,建议不要使用malloc/free来申请动态内存。需要的时候使用一个数组代替即可。
而对于uc/os系统,为了防止内存碎片及malloc带来的系统开销影响其实时性。uc/os操作系统本身也实现了一种对内存的管理,通过链表,管理不同的内存单元、内存块,在某种程度上解决了内存碎片问题,但是管理比较粗糙,一般建议不要大量使用。

■网友
没有操作系统,就是裸机。整台机器就你一个程序,享有全部的内存空间。CPU运行之初,会设置好栈空间的起始地址。堆空间的起始地址是编译器根据代码段和数据段的地址和大小推算出来的。栈从高往低长,堆从低往高长。
栈的管理比较简单,调用函数的时候会有压栈和出栈的动作,编译器已经生成好了这些代码。
【嵌入式C语言的堆栈管理怎样实现】 堆的管理,调用malloc,因为一般单片机的编译器都有特定的修改,支持动态分配内存,例如分配和释放内存,空闲内存的管理。但是管理算法比较简单,会出现内存碎片。


推荐阅读