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

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

GFP_ATOMIC
The allocation is high-priority and does not sleep. This is the flag to use in interrupt handlers, bottom halves and other situations where you cannot sleep.

GFP_KERNEL This is a normal allocation and might block. This is the flag to use in process context code when it is safe to sleep.

Хорошая статья о vmalloc и kmalloc http://learnlinuxconcepts.blogspot.in/2014/02/linux-memory-m‌ anagement.html

JIN007 15.02.2014 19:35

В этой статье утверждается чушь вроде: «Обычно 32-битная архитектура имеет размер страницы 4 КБ, а 64-битная архитектура имеет размер страницы 8 КБ». Я не прочитал его полностью, но я бы не назвал его "хорошим" и даже не стал бы доверять ни единому слову из этого.

Alexandro Sánchez 29.10.2018 01:00

Примечание (частично связанное): vmalloc быстрее с ядром 5.2 (2 квартал 2019 г.)

VonC 20.05.2019 19:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
120
3
108 321
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

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

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

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

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

FreeMemory 22.09.2008 21:54

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

Dark Shikari 22.09.2008 21:58

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

FreeMemory 22.09.2008 22:00

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

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

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

«потому что ядро ​​редко использует виртуальную память», но почему?

Trey 14.11.2017 23:42

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

Mike Heinz 02.04.2019 02:06

Нет, память ядра, выделенная с помощью vmalloc, заменена никогда. Поменять местами можно только память пользовательского пространства. Адресное пространство ядра не подлежит замене, и vmalloc выделяется в адресном пространстве ядра.

user2679859 27.02.2020 23:22
Ответ принят как подходящий

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

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

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

*)This was true of earlier kernels. On recent kernels (I tested this on 2.6.33.2), max size of a single kmalloc is up to 4 MB! (I wrote a fairly detailed post on this.) — kaiwan

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

Я думал, что системные вызовы были введены путем запуска int $ 0x80? (т.е. прерывание)?

FreeMemory 22.09.2008 23:01

int $ 0x80 - это программное прерывание, также называемое ловушкой. Под обработчиками прерываний подразумевается аппаратное прерывание, например, когда пользователь нажимает клавишу или перемещает ходы.

Branan 22.09.2008 23:21

Системные вызовы предназначены для переходов из пользовательского пространства в пространство ядра ... kmalloc используется только в контексте ядра ??

AIB 02.07.2009 13:28

@FreeMemory: int $ 0x80 зависит от x86, и, кроме того, это также старый метод, замененный sysenter / syscall (на x86).

jørgensen 14.03.2012 03:29

Спасибо за ответ, дающий понимание. Таким образом, vmalloc распределяет постранично виртуальные физическим страницам. Когда вы сказали, что kmalloc никогда не выполняет переназначение, что вы имеете в виду? Имеется ли в ядре предварительно выделенная виртуально-физическая область для kmalloc (постоянно выделяемая)?

Chan Kim 01.09.2020 09:44

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по теме