Как malloc () реализуется внутри компании? [дубликат]
этот вопрос уже есть ответ здесь:
- Как работают malloc () и free ()? 14 ответов
может ли кто-нибудь объяснить, как malloc()
работает внутри?
Я иногда делал strace program
и я вижу много sbrk
системные вызовы, выполнение man sbrk
говорит о том, что он используется в malloc()
но не более того.
3 ответа:
The
sbrk
системный вызов перемещает "границу" сегмента данных. Это означает, что он перемещает границу области, в которой программа может читать / записывать данные (позволяя ей расти или сжиматься, хотя AFAIK нетmalloc
действительно возвращает сегменты памяти ядру с помощью этого метода). Кроме того, есть такжеmmap
, который используется для отображения файлов в память, но также используется для выделения памяти (Если вам нужно выделить общую память,mmap
Как вы делаете это).у вас есть два способы получения большего объема памяти из ядра:
malloc реализация может создавать сегменты для 16, 64, 256 и 1024 байтовых структур. Если вы спроситеsbrk
иmmap
. Существуют различные стратегии по организации памяти, которую вы получили от ядра.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 память будет "поддерживаться" фактическими физическими страницами при доступе к этому диапазону адресов, что приведет к ошибке страницы и в конечном итоге приведет к вызову ядра в распределитель страниц для получения резервной страницы.