Malloc实现 – 困惑

我正在尝试为练习创建自己的malloc()。 我从这个post中得到了下面的代码。

typedef struct free_block { size_t size; struct free_block* next; } free_block; static free_block free_block_list_head = { 0, 0 }; // static const size_t overhead = sizeof(size_t); static const size_t align_to = 16; void* malloc(size_t size) { size = (size + sizeof(free_block) + (align_to - 1)) & ~ (align_to - 1); free_block* block = free_block_list_head.next; free_block** head = &(free_block_list_head.next); while (block != 0) { if (block->size >= size) { *head = block->next; return ((char*)block) + sizeof(free_block); } head = &(block->next); block = block->next; } block = (free_block*)sbrk(size); block->size = size; return ((char*)block) + sizeof(free_block); } void free(void* ptr) { free_block* block = (free_block*)(((char*)ptr) - sizeof(free_block )); block->next = free_block_list_head.next; free_block_list_head.next = block; } 

我对将内存块作为链表进行处理感到困惑。 在我看来,每当我们需要内存时,我们就会基本上调用sbrk(),并检查我们之前请求的某些内存是否在此期间未被释放。

但是我们无法检查属于其他进程的其他内存块,我们只检查之前请求的内存并添加到链表中。

如果是这种情况,这是最佳的吗? 这是标准malloc()的工作原理吗? 我们有办法处理堆上的所有内存吗?

请解释我5岁,我很难理解这个概念。

扩展流程数据段不会影响其他流程。 在大多数(最近的)架构上,进程内存模型是平坦的,即每个进程都有一个virtual地址空间( 2^322^64字节)。 当进程请求额外的内存(页面)时,会添加virtual内存进行处理。 实际上,这并不意味着发生任何物理内存分配,因为virtual内存可以映射到交换文件,或者在使用之前完全取消映射(地址被赋予进程,但没有分配给它的实际资源)。 内核负责根据需要/每个资源可用性将物理地址映射到virtual地址。

算法的作用是什么?

当用户调用malloc ,算法会尝试查找可用的空块。 在开始时,没有,因此算法尝试扩展过程数据段。

但是,您可以看到, free不会释放虚拟内存(因为它不像分配虚拟内存那样简单),而是将此已released块添加到未使用的块列表中。

因此,当有预先发布的块时, malloc尝试重用它们而不是extendind数据段。

标准malloc的工作原理如上:不。 您提供的示例很简单,但效率却很低。 有许多不同的算法可用于内存管理:小块堆(当分配数据达到一定数量时具有O(1)性能),特定于线程的分配器(减少从多个线程访问堆的拥塞),分配器,分配大块,然后使用它们(类似于上面,但更有效)和其他。

您可以尝试使用“内存堆实现”来获取更多信息