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

<p>я погуглил и обнаружил, что большинство людей выступает за использование <code>kmalloc</code>, поскольку вы гарантированно получите смежные физические блоки памяти. однако, также кажется, что <code>kmalloc</code> может потерпеть неудачу, если не может быть найден непрерывный блок <strong>физический</strong>, который вы хотите.<br> каковы преимущества наличия непрерывного блока памяти? в частности, зачем мне иметь непрерывный <strong>физический</strong> блок памяти в <em> системном вызове </em>? есть ли причина, по которой я не мог просто использовать <code>vmalloc</code>?<br> наконец, если бы я должен был выделить память во время обработки системного вызова, я должен указать <code>gfp\_atomic</code>? системный вызов выполняется в атомарном контексте?</p><blockquote> <p><code>gfp\_atomic</code><br> распределение является приоритетным и не спит. этот флаг используется в обработчиках прерываний, нижних половинах и других ситуациях, когда вы не можете спать.</p> <p><code>gfp\_kernel</code> это нормальное распределение и может блокироваться. этот флаг используется в коде контекста процесса, когда он безопасен для сна.</p> </blockquote>

<p>вам следует беспокоиться об использовании физически непрерывной памяти, если к буферу будет обращаться устройство dma по физически адресуемой шине (например, pci). проблема в том, что многие системные вызовы не имеют возможности узнать, будет ли их буфер в конечном итоге передан устройству dma: как только вы передадите буфер в другую подсистему ядра, вы действительно не сможете знать, куда он пойдет. , даже если ядро не использует буфер для dma <i>сегодня,</i> будущее развитие может сделать это.</p><p>vmalloc часто медленнее, чем kmalloc, поскольку может потребоваться переназначить пространство буфера в практически непрерывный диапазон. kmalloc никогда не перераспределяется, хотя, если не вызывается с gfp\_atomic, kmalloc может блокироваться.</p><p>размер kmalloc ограничен буфером, который он может предоставить: 128 кб<sup>*)</sup>, если вам нужен действительно большой буфер, вы должны использовать vmalloc или какой-то другой механизм, такой как резервирование высокой памяти при загрузке.</p><blockquote> <p><sup>*)</sup> <em> это было верно для более ранних ядер. в последних ядрах (я проверял это на 2.6.33.2) максимальный размер одного kmalloc составляет до 4 мб! (я написал довольно <a href="http://kaiwantech.wordpress.com/2011/08/17/kmalloc-and-vmalloc-linux-kernel-memory-allocation-api-limits/">подробный пост об этом</a> .) - kaiwan </em></p> </blockquote><p>для системного вызова вам не нужно передавать gfp\_atomic в kmalloc (), вы можете использовать gfp\_kernel. вы не обработчик прерываний: код приложения входит в контекст ядра посредством ловушки, это не прерывание.</p>

<p>краткий ответ: скачайте <a href="http://lwn.net/kernel/ldd3/">драйверы устройств linux</a> и прочитайте главу об управлении памятью.</p><p>серьезно, есть много тонких проблем, связанных с управлением памятью ядра, которые вы должны понять - я трачу много времени на отладку проблем с ним.</p><p>vmalloc () используется очень редко, потому что ядро редко использует виртуальную память. kmalloc () - это то, что обычно используется, но вы должны знать, каковы последствия различных флагов, и вам нужна стратегия, чтобы справиться с тем, что происходит, когда он терпит неудачу - особенно если вы находитесь в обработчике прерываний, как вы и предлагали.</p>

<p>разработка ядра linux робертом лавом (глава 12, стр. 244 в 3-м издании) очень четко отвечает на это.</p><p>да, физически непрерывная память не требуется во многих случаях. основной причиной использования kmalloc в ядре больше, чем vmalloc, является производительность. в книге объясняется, что когда большие фрагменты памяти выделяются с помощью vmalloc, ядро должно отображать физически несмежные фрагменты (страницы) в одну непрерывную область виртуальной памяти. поскольку память является практически непрерывной и физически несмежной, в таблицу страниц необходимо добавить несколько сопоставлений виртуальных и физических адресов. и в худшем случае будет <em> (размер буфера/размер страницы) </em> количество отображений, добавленных в таблицу страниц.</p><p>это также добавляет нагрузку на tlb (записи кэша, хранящие недавние сопоставления виртуальных и физических адресов) при доступе к этому буферу. это может привести к <a href="http://en.wikipedia.org/wiki/thrashing\_%28computer\_science%29">избиению</a> .</p>

<p>функции <code>kmalloc()</code> & <code>vmalloc()</code> представляют собой простой интерфейс для получения памяти ядра в кусках размером в байты.</p><ol> <li> <p>функция <code>kmalloc()</code> гарантирует, что страницы являются физически смежными (и практически смежными).</p> </li> <li> <p>функция <code>vmalloc()</code> работает аналогично функции <code>kmalloc()</code>, за исключением того, что она выделяет память, которая является только виртуально смежной и необязательно физически смежной.</p> </li> </ol>

<p><em> каковы преимущества наличия непрерывного блока памяти? в частности, зачем мне иметь непрерывный физический блок памяти в системном вызове? есть ли причина, по которой я не мог просто использовать vmalloc? </em></p><p>из google "мне повезет" на <code>vmalloc</code>:</p><p><strong>kmalloc является предпочтительным способом, если вам не нужны очень большие области. проблема в том, что если вы хотите выполнить dma с/на какое-либо аппаратное устройство, вам необходимо используйте kmalloc, и вам, вероятно, понадобится больший кусок. решение состоит в том, чтобы выделить память как можно скорее, прежде чем память будет фрагментирована.</strong></p>

<p>в 32-битной системе kmalloc () возвращает логический адрес ядра (хотя это и виртуальный адрес), который имеет прямое отображение (фактически с постоянным смещением) на физический адрес. это прямое сопоставление гарантирует, что мы получим непрерывный физический кусок оперативной памяти. подходит для dma, где мы даем только начальный указатель и после этого ожидаем непрерывное физическое отображение для нашей операции.</p><p>vmalloc () возвращает виртуальный адрес ядра, который, в свою очередь, может не иметь непрерывного отображения в физической памяти. полезно для выделения большого объема памяти и в тех случаях, когда мы не заботимся о том, чтобы память, выделенная для нашего процесса, была непрерывной и в физической памяти.</p>

<p>одним из других отличий является то, что kmalloc будет возвращать логический адрес (иначе вы указываете gpf\_highmem). логические адреса размещаются в "малой памяти" (в первом гигабайте физической памяти) и сопоставляются непосредственно с физическими адресами (используйте макрос \_\_pa для его преобразования). это свойство подразумевает, что kmalloced memory является непрерывной памятью.</p><p>с другой стороны, vmalloc может возвращать виртуальные адреса из "большой памяти". эти адреса не могут быть преобразованы в физические адреса прямым способом (вы должны использовать функцию virt\_to\_page).</p>