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

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

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

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

7 ответов


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

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

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

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

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


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

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

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


разработка ядра Linux Робертом Лав (Глава 12, Страница 244 в 3-м издании) отвечает на это очень четко.

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

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


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

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

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


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

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

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


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

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


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

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