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


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

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

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

7 98

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 (записи кэша, хранящие последние виртуальные сопоставления физических адресов) при доступе к этому буферу. Это может привести к thrashing.

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

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

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

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

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

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

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

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

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

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