В чем разница между vmalloc и kmalloc?

Я googled вокруг и нашел большинство людей, защищающих использование kmalloc , так как вы гарантированно получите смежные физические блоки памяти. Однако также кажется, что kmalloc может выйти из строя, если невозможно найти непрерывный физический блок, который вы хотите.
Каковы преимущества наличия непрерывного блока памяти? В частности, почему мне нужно иметь непрерывный физический блок памяти в системном вызове ? Есть ли причина, по которой я не мог просто использовать vmalloc ?
Наконец, если я должен был выделить память во время обработки системного вызова, должен ли я указывать GFP_ATOMIC ? Является ли системный вызов выполненным в атомном контексте?

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

GFP_KERNEL Это нормальное распределение и может блокироваться. Это флаг для использования в коде контекста процесса, когда он безопасен для сна.

7 Solutions collect form web for “В чем разница между vmalloc и kmalloc?”

Вам нужно только беспокоиться об использовании физически смежной памяти, если к буферу будет обращаться устройство DMA на физически адресуемой шине (например, PCI). Беда в том, что многие системные вызовы не имеют возможности узнать, будет ли их буфер в конечном итоге передан на устройство DMA: после того, как вы передадите буфер другой подсистеме ядра, вы действительно не можете знать, куда он будет идти. Даже если kernel ​​не использует буфер для DMA сегодня, это может сделать будущая разработка.

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

kmalloc ограничен размером буфера, который он может предоставить: 128 Кбайт *) . Если вам нужен действительно большой буфер, вам нужно использовать vmalloc или какой-либо другой механизм, например, резервировать высокую память при загрузке.

*) Это справедливо для ранних ядер. В последних ядрах (я тестировал это на 2.6.33.2) максимальный размер одного километрала до 4 МБ! (Я написал довольно подробный пост об этом .) – kaiwan

Для системного вызова вам не нужно передавать GFP_ATOMIC в kmalloc (), вы можете использовать GFP_KERNEL. Вы не обработчик прерываний: код приложения вводит контекст ядра с помощью ловушки, это не прерывание.

Краткий ответ: загрузите драйверы устройств Linux и прочитайте главу об управлении памятью.

Серьезно, есть много тонких проблем, связанных с управлением памятью ядра, которые вам нужно понять – я трачу много времени на отладку проблем с ним.

vmalloc () используется очень редко, потому что kernel ​​редко использует виртуальную память. kmalloc () – это то, что обычно используется, но вы должны знать, каковы последствия различных флагов, и вам нужна страtagsя для решения того, что происходит, когда она терпит неудачу, особенно если вы находитесь в обработчике прерываний, как вы предложили.

Linux Kernel Development от Robert Love (глава 12, стр. 244 в 3-м издании) отвечает на это очень четко.

Да, физически непрерывная память не требуется во многих случаях. Основной причиной использования kmalloc больше, чем vmalloc в ядре, является производительность. В книге объясняется, что, когда большие куски памяти выделяются с помощью vmalloc, kernel ​​должно отображать физически несмежные куски (страницы) в единую непрерывную область виртуальной памяти. Поскольку память является практически непрерывной и физически несмежной, в таблицу страниц должно быть добавлено несколько сопоставлений между виртуальными и физическими адресами. И в худшем случае будет (размер буфера / размер страницы) количество отображений, добавленных в таблицу страниц.

Это также добавляет давление на TLB (записи кэша, хранящие последние сопоставления виртуальных и физических адресов) при доступе к этому буферу. Это может привести к изнашиванию .

Функции kmalloc() & vmalloc() – это простой интерфейс для получения памяти ядра в кусках размера байта.

  1. Функция kmalloc() гарантирует, что страницы физически смежны (и практически смежны).

  2. Функция vmalloc() работает аналогично kmalloc() , за исключением того, что она выделяет память, которая только практически смежная и не обязательно физически смежная.

Каковы преимущества наличия непрерывного блока памяти? В частности, почему мне нужно иметь непрерывный физический блок памяти в системном вызове? Есть ли причина, по которой я не мог просто использовать vmalloc?

Из Google «Я чувствую себя счастливым» на vmalloc :

kmalloc является предпочтительным способом, если вам не нужны очень большие площади. Проблема в том, что если вы хотите сделать DMA с / на какое-то аппаратное устройство, вам нужно будет использовать kmalloc, и вам, вероятно, понадобится больший кусок. Решение заключается в том, чтобы как можно скорее выделить память, прежде чем память будет fragmentирована.

Одним из других отличий является то, что kmalloc вернет логический адрес (иначе вы укажете GPF_HIGHMEM). Логические адреса помещаются в «низкую память» (в первом гигабайте физической памяти) и отображаются непосредственно на физические адреса (используйте макрос __pa для его преобразования). Это свойство подразумевает, что память в километрах – это непрерывная память.

С другой стороны, Vmalloc может возвращать виртуальные адреса из «высокой памяти». Эти адреса не могут быть преобразованы в физические адреса напрямую (вы должны использовать функцию virt_to_page).

В 32-битной системе kmalloc () возвращает логический адрес ядра (его виртуальный адрес), который имеет прямое сопоставление (фактически с постоянным смещением) по физическому адресу. Это прямое отображение гарантирует, что мы получим смежный физический кусок ОЗУ. Подходит для DMA, где мы даем только начальный указатель и ожидаем последующего физического отображения после этого для нашей операции.

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

Давайте будем гением компьютера.