在许多嵌入式系统中,内存碎片是一个问题。特别是对于长时间运行(数月、数年等)的软件。对于许多项目,解决方案是简单地不使用动态内存分配,例如 malloc/free 和 new/delete。尽可能使用全局内存,频繁分配和释放类型的内存池是避免使用动态内存管理的好策略。
在嵌入式 Linux 中,这是如何解决的?我看到许多库使用动态内存。操作系统是否有防止内存碎片的机制?它会定期清理堆吗?还是应该避免在嵌入式环境中使用这些库?
在许多嵌入式系统中,内存碎片是一个问题。特别是对于长时间运行(数月、数年等)的软件。对于许多项目,解决方案是简单地不使用动态内存分配,例如 malloc/free 和 new/delete。尽可能使用全局内存,频繁分配和释放类型的内存池是避免使用动态内存管理的好策略。
在嵌入式 Linux 中,这是如何解决的?我看到许多库使用动态内存。操作系统是否有防止内存碎片的机制?它会定期清理堆吗?还是应该避免在嵌入式环境中使用这些库?
没有非移动内存分配器可以避免至少一个 log(M/m) 因子的碎片,其中 M = 最大对象请求的大小,m = 最小对象的大小(这是由于致罗布森,1971 年)。
我与从事实时系统编程的人一起工作(包括在空中客车公司),他们刻意避免使用动态内存分配,而是使用池,正如你提到的。
但是,操作系统和内存分配之间存在很大差异。向程序员公开的动态内存分配是库的一部分,与操作系统几乎没有关系(作为内存来源除外)。Linux 本身使用基于slab 的内存分配器来实现其内部目的;我认为嵌入式 Linux 也是如此,但不确定。
这取决于你如何使用内存。
Linux 在大多数情况下使用虚拟内存,其中应用程序将内存视为连续的内存块。底层内核完成了虚拟内存和物理内存之间的所有手动映射,因此您不必处理它。从物理上讲,您的内存可能会四处散落,但您的应用程序看不到这一点。
现在,如果你真的想要连续的物理内存怎么办?当您想要执行 DMA 或硬件的其他一些硬要求时,通常会发生这种情况。在这种情况下,您可以分配指向特定物理内存的内存页面。但是你必须把它作为一个例外而不是规范。
我设计我的系统的方式是让大多数驱动程序(“实时”驱动程序除外)进入用户空间。这样你就可以获得用户空间的所有好处(更多的库、语言),如果你有一个错误,不要杀死内核,并利用可用的虚拟内存。
恕我直言,无论哪种情况,您都可以搜索内存分配算法,从而减少碎片。并且,在测量您的内存需求后配置此算法或您的内存分配实现。
我可以推荐TLSF作为开始。