Какой системный вызов использует Mallo c? - PullRequest
2 голосов
/ 28 апреля 2020

Я изучаю управление памятью и у меня есть вопрос о том, как работает Mallo c. Страница mallo c man гласит, что:

Обычно malloc() выделяет память из кучи и корректирует размер кучи по мере необходимости, используя sbrk(2) , При выделении блоков памяти размером более MMAP_THRESHOLD байтов реализация glib c malloc() выделяет память как частное анонимное отображение, используя mmap(2). MMAP_THRESHOLD по умолчанию составляет 128 кБ, но настраивается с помощью 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;
}

I проследил эту программу с помощью strace , чтобы увидеть, какой системный вызов использовался. Вот результат:

strace result

Почему в этом примере mallo c вызвал mmap вместо brk?

Ответы [ 2 ]

3 голосов
/ 28 апреля 2020

Все эти mmap() вызовы являются частью запуска вашей программы при загрузке общих библиотек. Это стандартная вещь, которую вы увидите, когда вы strace большинство программ.

Реальное действие заключается в последних нескольких строках:

  • Два вызова brk() из malloc().
  • Вызов fstat() и write() из printf().

Вы можете добавить распечатку в начало main(), чтобы узнать, когда ваш код фактически запускается.

(Важно вызывать системный вызов write() напрямую, а не печатать с помощью printf() или puts(). Функции stdio вызывают внутри malloc(), что мешает нам пытаясь проверить.)

#include <unistd.h>

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

    ...
}

Когда я это делаю, я вижу вызов write() прямо перед brk(NULL), который я пометил ниже пустой строкой:

...
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 голосов
/ 28 апреля 2020

Большинство libc реализаций с открытым исходным кодом. Изучите исходный код glib c или musl-lib c. Оба реализуют malloc и free. Используйте также strace (1)

Обычно они используют mmap (2) или иногда sbrk (2)

Конечно, они пытаются минимизировать количество системных вызовов, по крайней мере, для небольших объемов памяти.

...