【问题标题】:What syscall does malloc use?malloc 使用什么系统调用?
【发布时间】:2020-08-12 17:31:54
【问题描述】:

我正在研究内存管理,并且对 malloc 的工作原理有疑问。 malloc man page 声明:

通常,malloc() 从堆中分配内存,并调整 堆大小根据需要使用sbrk(2)。分配块时 大于MMAP_THRESHOLD 字节的内存,glibc malloc() 实现将内存分配为私有匿名映射 使用mmap(2)MMAP_THRESHOLD 默认为 128 kB,但 使用mallopt(3)进行调整。

为了验证,我用一段代码做了一个实验:

#include<stdlib.h>
#include<stdio.h>

int main()
{
    int size = 10;
    int *p = malloc(size);

    if(p)
    {
        printf("allocated %d bytes at addr: %p \n", size, p);
        free(p);
    }
    else
    {
        free(p);
    }

    return 0;
}

我用strace 跟踪了这个程序,看看使用了什么系统调用。结果如下:

为什么在这个例子中 malloc 调用 mmap 而不是 brk?

【问题讨论】:

  • 您的屏幕截图清楚地显示了对brk 的调用,而不是对mmap 的调用(尽管不确定是您的malloc 引起的,因为malloc 在没有系统调用的情况下分块分配和打包) .您是否对流程初始化中的mmap 调用感到困惑?只是做例如printf("Hello World\n") 查看初始化何时结束以及您的 main 何时开始。

标签: c linux memory-management malloc


【解决方案1】:

所有这些mmap() 调用都是程序在加载共享库时启动的一部分。这是您在strace 大多数程序时会看到的标准内容。

真正的动作在最后几行:

  • 来自malloc() 的两次对brk() 的调用。
  • 来自printf()fstat()write() 呼叫。

您可以在main() 的顶部添加打印输出,以查看您的代码何时真正开始运行。

(重要的是直接调用write() 系统调用,而不是使用printf()puts() 打印。stdio 函数在内部调用malloc(),这混淆了我们正在尝试测试的内容。)支持>

#include <unistd.h>

int main()
{
    write(1, "start\n", 6);

    ...
}

当我这样做时,我在 brk(NULL) 之前看到了 write() 调用,我在下面用空行标记:

...
mmap(0x7f1b34802000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e7000) = 0x7f1b34802000
mmap(0x7f1b34808000, 15072, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f1b34808000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7f1b34a124c0) = 0
mprotect(0x7f1b34802000, 16384, PROT_READ) = 0
mprotect(0x558c3cd9a000, 4096, PROT_READ) = 0
mprotect(0x7f1b34a33000, 4096, PROT_READ) = 0
munmap(0x7f1b34a13000, 128122)          = 0

write(1, "start\n", 6)                  = 6
brk(NULL)                               = 0x558c3dc58000
brk(0x558c3dc79000)                     = 0x558c3dc79000
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 4), ...}) = 0
write(1, "allocated 10 bytes at addr: 0x55"..., 44) = 44
exit_group(0)                           = ?
+++ exited with 0 +++

【讨论】:

    【解决方案2】:

    大多数libc 实现都是开源的。研究glibc或的源代码 musl-libc。两者都实现了mallocfree。也可以使用strace(1)

    通常,他们使用mmap(2) 或有时sbrk(2)

    当然,他们会尽量减少系统调用的次数,至少对于小内存大小是这样。

    【讨论】:

    • 请注意,如今 sbrk 是一个调用 brk 系统调用的库函数。
    猜你喜欢
    • 2021-11-08
    • 1970-01-01
    • 2013-08-04
    • 2011-09-13
    • 1970-01-01
    • 1970-01-01
    • 2014-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多