В чем разница между vmalloc и kmalloc? - PullRequest
104 голосов
/ 22 сентября 2008

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

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

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

Ответы [ 7 ]

85 голосов
/ 22 сентября 2008

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

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

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

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

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

16 голосов
/ 22 сентября 2008

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

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

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

12 голосов
/ 12 июля 2012

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

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

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

10 голосов
/ 30 ноября 2015

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

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

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

5 голосов
/ 22 сентября 2008

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

Из Google "Мне повезет" на vmalloc:

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

2 голосов
/ 05 ноября 2017

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

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

1 голос
/ 12 марта 2012

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

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

...