malloc期间在内核中会发生什么?

面试中我被问到了这个问题。 他们想知道的是,当用户调用malloc(4)分配4个字节的内存时,操作系统(Linux)如何响应? 哪个子系统响应这个系统调用?

我告诉他malloc()将由内存pipe理子系统服务。 malloc()实现将遍历空闲内存列表(物理内存),我们将其称为空闲列表,并find大于或等于4字节的相应块。 一旦find这样的块,它将从空闲列表中删除并添加到使用的列表。 然后,这个物理内存将被映射到进程堆vma结构。 他似乎对这个答案并不满意。伙伴系统如何适应这个问题呢? 任何帮助将不胜感激。

当用户空间应用程序调用malloc() ,该调用不在内核中实现。 相反,这是一个库调用(实施glibc或类似的)。

简短的版本是,glibc中的malloc实现通过mmap()brk() / sbrk()系统调用或匿名内存中获取内存。 这给了glibc一个很大的连续(关于虚拟内存地址)内存块, malloc实现进一步切片并以较小的块切块并交给你的应用程序。

这里有一个小的malloc实现,可以给你这个想法,还有很多很多的链接。

请注意,没有关心物理内存的问题 – 当内存虚拟内存系统通过brk() / sbrk()mmap()更改进程数据段时,以及内存被引用时(通过读取或写入到内存)。

总结:

  1. malloc()将search其托pipe的内存块,以查看是否有一块未满足分配要求的未使用的内存。
  2. 否则, malloc()会尝试扩展过程数据段(通过sbrk() / brk()或在某些情况下mmap() )。 sbrk()结束在内核中。
  3. 内核中的brk() / sbrk()调用会调整进程的struct mm_struct中的一些偏移量,所以进程数据段将会更大。 首先,没有物理内存映射到扩展数据段给出的附加虚拟地址。
  4. 当第一次触摸未映射的内存时(可能是malloc实现的读/写),故障处理程序将会启动并捕获到内核,内核将在内核中将物理内存分配给未映射的内存。

你的答案有一个错误 – malloc 直接处理物理内存。 它涉及分页的虚拟内存 – 虽然我不确定是否对每个架构都是如此。

当您的程序尝试分配内存并且空闲列表不包含大小等于或大于所请求大小的块时,将分配整个新页面。 页面大小取决于体系结构(x86上的4096字节)。 页面分配是只有内核可以执行的事情,因此malloc调用可能会导致系统调用。 然后将新地址添加到空闲列表中, malloc根据其实现操作空闲列表(例如,检查glibc)。