что такое высокая и низкая память в linux?

<p>меня интересует разница между highmem и lowmem:</p><ol> <li>почему существует такая дифференциация?</li> <li>что мы получаем от этого?</li> <li>какие функции есть у каждого?</li> </ol>

<p>в 32-разрядной архитектуре диапазон адресного пространства для адресации ram равен:</p><pre><code>0x00000000 - 0xffffffff </code></pre><p>или <code>4'294'967'295</code> (4гб).</p><p>ядро linux делит это на 3/1 (также может быть 2/2 или 1/3 <sup>1</sup>) в пространство пользователя (высокий объем памяти) и пространство ядра (низкий объем памяти) соответственно.</p><p>диапазон пространства пользователя:</p><pre><code>0x00000000 - 0xbfffffff </code></pre><p>каждый недавно созданный пользовательский процесс получает адрес (диапазон) внутри этой области. пользовательские процессы обычно не заслуживают доверия и поэтому им запрещен доступ к пространству ядра. кроме того, они считаются несрочными, поскольку, как правило, ядро пытается отложить выделение памяти этим процессам.</p><p>диапазон пространства ядра:</p><pre><code>0xc0000000 - 0xffffffff </code></pre><p>процессы ядра получают свой адрес (диапазон) здесь. ядро может напрямую обращаться к этим 1 гб адресов (ну, не полный 1 гб, есть 128 мб, зарезервированных для доступа к высокой памяти).</p><p>процессы, порожденные в пространстве ядра, являются доверенными, срочными и предполагаемыми безошибочными, запрос памяти обрабатывается мгновенно.</p><p>каждый процесс ядра может также получить доступ к диапазону пространства пользователя, если он этого хочет. и чтобы достичь этого, ядро отображает адрес из пользовательского пространства (высокая память) в его пространство ядра (низкая память), упомянутые выше 128 мб специально зарезервированы для этого.</p><hr><p><sup>1</sup> является ли разделение 3/1, 2/2 или 1/3, контролируется <code>config\_vmsplit\_...</code> опция; вы можете проверить под <code>/boot/config*</code> чтобы увидеть, какая опция была выбрана для вашего ядра.</p>

<p>первое упоминание: <a href="http://lwn.net/kernel/ldd3/">драйверы устройств linux</a> (доступно как онлайн, так и в виде книги), в частности <a href="http://lwn.net/images/pdf/ldd3/ch15.pdf">глава 15</a> , в котором есть раздел на эту тему.</p><p>в идеальном мире каждый системный компонент сможет отобразить всю память, к которой ему когда-либо понадобится доступ. и это относится к процессам в linux и большинстве операционных систем: 32-разрядный процесс может получить доступ только к чуть менее 2 ^ 32 байтов виртуальной памяти (фактически около 3 гб в типичной 32-разрядной архитектуре linux). это становится трудным для ядра, которое должно иметь возможность отображать полную память процесса, системный вызов которого он выполняет, плюс всю физическую память плюс любое другое отображаемое в памяти аппаратное устройство.</p><p>поэтому, когда 32-разрядному ядру необходимо отобразить более 4 гб памяти, оно должно быть скомпилировано с поддержкой высокой памяти. высокая память - это память, которая не отображается постоянно в адресном пространстве ядра. (недостаточно памяти наоборот: она всегда отображается, поэтому вы можете получить к ней доступ в ядре, просто разыменовав указатель.)</p><p>когда вы обращаетесь к большой памяти из кода ядра, вам сначала нужно вызвать <code>kmap</code>, чтобы получить указатель из структуры данных страницы (<code>struct page</code>). вызов <code>kmap</code> работает независимо от того, находится ли страница в большом или низком объеме памяти. есть также <code>kmap\_atomic</code>, который добавил ограничения, но более эффективен на многопроцессорных машинах, потому что он использует более тонкую блокировку. указатель, полученный через <code>kmap</code>, является ресурсом: он использует адресное пространство. как только вы закончили с этим, вы должны вызвать <code>kunmap</code> (или <code>kunmap\_atomic</code>) освободить этот ресурс; тогда указатель больше не действителен, и содержимое страницы не может быть доступно, пока вы не вызовете <code>kmap</code> снова.</p>

<p>это относится к ядру linux; я не уверен, как любое ядро unix справляется с этим.</p><p>большая память - это сегмент памяти, к которому могут обращаться программы пользовательского пространства. это не может коснуться малой памяти.</p><p>недостаток памяти - это сегмент памяти, к которому ядро linux может обращаться напрямую. если ядро должно получить доступ к high memory, оно должно сначала отобразить его в своем собственном адресном пространстве.</p><p>недавно был выпущен патч, который позволяет вам контролировать, где находится сегмент. компромисс заключается в том, что вы можете забрать адресуемую память из пространства пользователя, чтобы у ядра было больше памяти, которую ему не нужно отображать перед использованием.</p><p>дополнительные ресурсы:</p><ul> <li> <a href="http://tldp.org/howto/kernelanalysis-howto-7.html">http://tldp.org/howto/kernelanalysis-howto-7.html</a> </li> <li> <a href="http://linux-mm.org/highmemory">http://linux-mm.org/highmemory</a> </li> </ul>

<p>highmem - это область памяти ядра, но это не память, к которой вы обращаетесь, а место, куда вы помещаете то, что хотите получить.</p><p>типичная 32-битная карта виртуальной памяти linux выглядит так:</p><ul> <li> <p>0x00000000-0xbfffffff: пользовательский процесс (3 гб)</p> </li> <li> <p>0xc0000000-0xffffffff: пространство ядра (1 гб)</p> </li> </ul><p>(вектор, специфичный для процессора, и все остальное здесь игнорируется).</p><p>linux разделяет пространство ядра в 1 гб на 2 части, lowmem и highmem. разделение варьируется от установки к установке.</p><p>если установка выбирает, скажем, 512 мб-512 мб для низкого и высокого мемов, то 512 мб lowmem (0xc0000000-0xdfffffff) статически отображается во время загрузки ядра; обычно для этого используются первые столько байтов физической памяти, чтобы виртуальные и физические адреса в этом диапазоне имели постоянное смещение, скажем, 0xc0000000.</p><p>с другой стороны, последние 512 мб (highmem) не имеют статического сопоставления (хотя вы можете оставить там полупостоянное отображение страниц, но вы должны сделать это явно в коде вашего драйвера). вместо этого страницы временно отображаются и не отображаются здесь, так что виртуальные и физические адреса в этом диапазоне не имеют согласованного отображения. типичное использование highmem включает одноразовые буферы данных.</p>

<p>насколько я помню, "high memory" используется для пространства приложения, а "low memory" для ядра.</p><p>преимущество заключается в том, что приложения (пользовательского пространства) не могут получить доступ к памяти пространства ядра.</p>

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