Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

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

Для системного вызова вам не нужно передавать 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, и вам, вероятно, понадобится больший кусок.Решение состоит в том, чтобы распределить память как можно скорее, прежде чем память не станет фрагментирована.

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top