Я погуглил и нашел, что большинство людей выступают за использование kmalloc
, поскольку вы гарантированно получите непрерывные физические блоки памяти. Однако также кажется, что он kmalloc
может потерпеть неудачу, если не удается найти непрерывный физический блок, который вам нужен.
Каковы преимущества непрерывного блока памяти? В частности, зачем мне иметь непрерывный физический блок памяти в системном вызове ? Есть ли причина, по которой я не могу просто использовать vmalloc
?
Наконец, если бы я должен был выделить память во время обработки системного вызова, должен ли я указать GFP_ATOMIC
? Системный вызов выполняется в атомарном контексте?
GFP_ATOMIC
Выделение имеет высокий приоритет и не спит. Этот флаг используется в обработчиках прерываний, нижних половинах и других ситуациях, когда вы не можете спать.
GFP_KERNEL
Это нормальное распределение, которое может блокировать. Это флаг, который следует использовать в коде контекста процесса, когда можно безопасно спать.
источник
vmalloc
работает быстрее с Kernel 5.2 (второй квартал 2019 г.)Ответы:
Вам нужно только беспокоиться об использовании физически непрерывной памяти, если к буферу будет обращаться устройство DMA на физически адресуемой шине (например, PCI). Проблема в том, что многие системные вызовы не имеют возможности узнать, будет ли их буфер в конечном итоге передан на устройство DMA: как только вы передаете буфер другой подсистеме ядра, вы действительно не можете знать, куда он собирается. Даже если ядро не использует буфер для DMA сегодня, это может быть сделано в будущих разработках.
vmalloc часто работает медленнее, чем kmalloc, потому что может потребоваться переназначить буферное пространство в практически непрерывный диапазон. kmalloc никогда не переназначается, хотя, если он не вызван с GFP_ATOMIC, kmalloc может заблокироваться.
kmalloc ограничен размером буфера, который он может предоставить: 128 КБ *) . Если вам нужен действительно большой буфер, вы должны использовать vmalloc или какой-либо другой механизм, например резервирование верхней памяти при загрузке.
Для системного вызова вам не нужно передавать GFP_ATOMIC в kmalloc (), вы можете использовать GFP_KERNEL. Вы не обработчик прерывания: код приложения входит в контекст ядра с помощью ловушки, это не прерывание.
источник
Краткий ответ: скачайте драйверы устройств Linux и прочтите главу об управлении памятью.
Серьезно, есть много тонких проблем, связанных с управлением памятью ядра, которые вам нужно понять - я трачу много времени на отладку с этим.
vmalloc () используется очень редко, потому что ядро редко использует виртуальную память. kmalloc () - это то, что обычно используется, но вы должны знать, каковы последствия различных флагов, и вам нужна стратегия для того, чтобы справиться с тем, что происходит, когда он выходит из строя, особенно если вы находитесь в обработчике прерывания, как вы предложили.
источник
Роберт Лав (глава 12, стр. 244 в 3-м издании) "Разработка ядра Linux" дает очень четкий ответ на этот вопрос.
Да, во многих случаях физически непрерывная память не требуется. Основная причина того, что kmalloc используется в ядре больше, чем vmalloc, - это производительность. В книге объясняется, что когда большие фрагменты памяти выделяются с помощью vmalloc, ядро должно отображать физически несмежные фрагменты (страницы) в единую непрерывную область виртуальной памяти. Поскольку память практически непрерывна и физически не непрерывна, в таблицу страниц необходимо добавить несколько отображений виртуальных адресов в физические. И в худшем случае в таблицу страниц будет добавлено (размер буфера / размер страницы) количество отображений.
Это также увеличивает нагрузку на TLB (записи кэша, хранящие недавние сопоставления виртуальных адресов с физическими) при доступе к этому буферу. Это может привести к взбучке .
источник
Функции
kmalloc()
&vmalloc()
представляют собой простой интерфейс для получения памяти ядра фрагментами размером в байты.kmalloc()
Функция гарантирует , что страницы физически смежные (и практически непрерывные).vmalloc()
Функция работает аналогично томуkmalloc()
, кроме него выделяет память, только практически непрерывным и не обязательно физически непрерывными.источник
Каковы преимущества непрерывного блока памяти? В частности, зачем мне иметь непрерывный физический блок памяти в системном вызове? Есть ли причина, по которой я не могу просто использовать vmalloc?
Из Google "Мне повезет" на
vmalloc
:kmalloc - предпочтительный способ, если вам не нужны очень большие области. Проблема в том, что если вы хотите выполнять DMA с / на какое-то аппаратное устройство, вам нужно использовать kmalloc, и вам, вероятно, понадобится больший кусок. Решение состоит в том, чтобы выделить память как можно скорее, прежде чем память станет фрагментированной.
источник
В 32-битной системе kmalloc () возвращает логический адрес ядра (хотя это виртуальный адрес), который имеет прямое отображение (фактически с постоянным смещением) на физический адрес. Это прямое сопоставление гарантирует, что мы получим непрерывный физический кусок ОЗУ. Подходит для прямого доступа к памяти, где мы указываем только начальный указатель и после этого ожидаем непрерывное физическое отображение для нашей операции.
vmalloc () возвращает виртуальный адрес ядра, который, в свою очередь, может не иметь непрерывного сопоставления с физической RAM. Полезно для выделения большого объема памяти и в тех случаях, когда нас не волнует, что память, выделенная нашему процессу, является непрерывной также в физической ОЗУ.
источник
Еще одно отличие - kmalloc вернет логический адрес (иначе вы укажете GPF_HIGHMEM). Логические адреса помещаются в «малую память» (в первый гигабайт физической памяти) и сопоставляются непосредственно с физическими адресами (используйте макрос __pa для его преобразования). Это свойство подразумевает, что выделенная память является непрерывной памятью.
С другой стороны, Vmalloc может возвращать виртуальные адреса из «верхней памяти». Эти адреса нельзя преобразовать в физические адреса напрямую (необходимо использовать функцию virt_to_page).
источник