Как malloc () реализуется внутри компании? [дубликат]


этот вопрос уже есть ответ здесь:

  • Как работают malloc () и free ()? 14 ответов

может ли кто-нибудь объяснить, как malloc() работает внутри?

Я иногда делал strace program и я вижу много sbrk системные вызовы, выполнение man sbrk говорит о том, что он используется в malloc() но не более того.

3 99

3 ответа:

The sbrkсистемный вызов перемещает "границу" сегмента данных. Это означает, что он перемещает границу области, в которой программа может читать / записывать данные (позволяя ей расти или сжиматься, хотя AFAIK нет malloc действительно возвращает сегменты памяти ядру с помощью этого метода). Кроме того, есть также mmap, который используется для отображения файлов в память, но также используется для выделения памяти (Если вам нужно выделить общую память, mmap Как вы делаете это).

у вас есть два способы получения большего объема памяти из ядра:sbrk и mmap. Существуют различные стратегии по организации памяти, которую вы получили от ядра.

malloc реализация может создавать сегменты для 16, 64, 256 и 1024 байтовых структур. Если вы спросите malloc чтобы дать вам память заданного размера он округляет это число до следующего размер ведра, а затем дает вам элемент из этого ведра. Если вам нужна большая площадь malloc можно использовать mmap для выделения непосредственно с ядром. Если ведро определенного размера пусто malloc можно использовать sbrk чтобы получить больше места для нового ведра.

различные malloc проектирует и, вероятно, нет ни одного истинного способа реализации malloc Как вам нужно сделать компромисс между скоростью, накладные расходы и избежать фрагментации / эффективности пространства. Например, если bucket runs out of elements реализация может получить элемент из большего ведра, разделить его и добавить в ведро, в котором закончились элементы. Это было бы довольно пространство эффективным, но не было бы возможно с каждым дизайном. Если вы просто получите еще одно ведро через sbrk/mmap это может быть быстрее и даже проще, но не так эффективно, как пространство. Кроме того, дизайн должен, конечно, учитывать, что" свободный " должен сделать пространство доступным для malloc опять как-то. Вы не просто раздаете память без повторного использования.

если вы заинтересованы, прокси OpenSER/Kamailio SIP имеет два malloc реализации (они нуждаются в своих собственных, потому что они делают интенсивное использование общей памяти и системы malloc не поддерживает общую память). Смотрите:https://github.com/OpenSIPS/opensips/tree/master/mem

тогда вы могли бы также посмотреть GNU libc malloc реализация, но это очень сложно, IIRC.

упрощенно malloc и свободная работа, как это:

malloc предоставляет доступ к куче процесса. Куча-это конструкция в библиотеке ядра C (обычно libc), которая позволяет объектам получать эксклюзивный доступ к некоторому пространству в куче процесса.

каждое выделение в куче называется ячейкой кучи. Это обычно состоит из заголовка, который содержит информацию о размере ячейки, а также указатель на следующую ячейку кучи. Это делает кучу эффективно связанной список.

при запуске процесса куча содержит одну ячейку, которая содержит все пространство кучи, назначенное при запуске. Эта ячейка существует в свободном списке кучи.

при вызове malloc память берется из большой ячейки кучи, которая возвращается malloc. Остальное формируется в новую ячейку кучи, которая состоит из всей остальной памяти.

когда вы освобождаете память, ячейка кучи добавляется в конец свободного списка кучи. Последующие выделяет область пешком в свободном списке ищем ячейку подходящего размера.

как и следовало ожидать, куча может быть фрагментирована, и менеджер кучи может время от времени пытаться объединить соседние ячейки кучи.

когда в свободном списке не осталось памяти для желаемого выделения, malloc вызывает brk или sbrk, которые являются системными вызовами, запрашивающими больше страниц памяти из операционной системы.

теперь есть несколько модификаций для оптимизации кучи оперативный.

  • для больших выделений памяти (обычно > 512 байт, куча менеджер может перейти прямо к ОС и выделите полную страницу памяти.
  • кучи может указать минимальный размер распределение для предотвращения больших сумм фрагментации.
  • куча также может разделиться на ячейки один для небольших распределений и один для больших распределений, чтобы сделать большие распределения быстрее.
  • есть также умные механизмы для оптимизация многопоточного распределения кучи.

также важно понимать, что простое перемещение указателя разрыва программы с помощью brk и sbrk не выделить память, она просто устанавливает адресное пространство. Например, в Linux память будет "поддерживаться" фактическими физическими страницами при доступе к этому диапазону адресов, что приведет к ошибке страницы и в конечном итоге приведет к вызову ядра в распределитель страниц для получения резервной страницы.