无操作系统的嵌入式系统中的malloc函数

12

这个问题涉及使用 malloc 来分配内存。

通常情况下,我们说 malloc 从堆中分配内存。

现在假设我有一个普通的嵌入式系统(没有操作系统),我加载了一个普通的程序,在程序中使用了 malloc

那么在这种情况下,内存是从哪里分配的呢?

3个回答

12

malloc()是一个通常由运行时库实现的函数。如果你在操作系统之上运行,那么malloc有时会(但并不总是)触发一个系统调用,使操作系统将一些内存映射到程序的地址空间中。

如果你的程序在没有操作系统的情况下运行,那么你可以把你的程序看作是操作系统。你可以访问所有地址,这意味着你可以将一个地址赋给指针,然后对它进行解引用以读写数据。

当然,你必须确保程序的其他部分不会使用同样的内存,因此你需要编写自己的内存管理器:

简单地说,你可以设置一系列地址,供你的 "内存管理器" 使用,用于存储哪些地址范围已经被使用(存储在其中的数据结构可以是链表或更复杂的结构)。然后,你将编写一个函数,例如 malloc(),作为内存管理器的功能部分。该函数查找上述数据结构,以找到与参数指定相同长度的可用地址范围,并返回指向它的指针。

现在,如果你的程序中的每个函数都调用你的 malloc() 而不是随机地写入自定义地址,那么你已经完成了第一步。你可以编写一个 free() 函数,在上述数据结构中查找给定的指针,并调整数据结构(在简单的链表中,它将合并两个链接)。


1
没有回答真正的问题:动态分配的内存去哪了。它进入堆中。堆在哪里?它在链接器脚本配置的地址范围内。 - Felipe Lavratti
2
@fanl,你的问题与Leo Messi的问题不同。你是否给这个答案点了-1?请撤销。如果你开一个新的问题,我会尽力回答它。 - Bernd Elkemann
1
这是一个很棒的思维实验,谢谢! - Max

5
唯一的真正答案是“取决于编译器/库的实现位置”。
在我使用的嵌入式系统中,没有堆,因为我们还没有编写过。

+1,当您启用优化时,编译器可能会选择堆栈,当它可以确定分配是本地的(例如,对于函数)。 - justin
好的,是真的,但也不是非常有帮助。 - Prof. Falken

4

如你所说,来自堆。不同之处在于堆不是由操作系统提供的。您的应用程序链接脚本无疑会包含对堆的分配。运行时库将管理此操作。

在基于GCC的嵌入式系统中经常使用的Newlib C库的情况下,该库具有一个名为sbrk()的存根syscall函数。开发人员的责任是实现sbrk(),以便在请求时为堆管理器提供更多内存。通常它仅增加指针并返回新块的起始指针,然后库的堆管理器管理和维护新块,该块可能与先前的块连续或不连续。前面的链接包括一个示例实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接