2009-04-15 4 views
23

У меня есть несколько вопросов относительно mmap реализации в системах Linux, которые не кажутся очень документировано:Linux MMAP внутренности

При отображении файла в память с помощью mmap, как бы вы справиться с предварительной выборкой данных в таком файл?

I.e. что происходит, когда вы читаете данные из mmaped региона? Эти данные перемещаются в кеши L1/L2? Является ли это прямое чтение из дискового кэша? Означает ли prefetchnta и аналогичные инструкции ASM на mmap зонах?

Что такое накладные расходы от фактического звонка mmap? Относительно количества отображаемых данных или констант?

Надеюсь, у кого-то есть некоторое представление об этом. Заранее спасибо.

ответ

29

mmap - это в основном программный доступ к подсистеме виртуальной памяти.

Если у вас есть, скажем, 1G-файл, и вы mmap его, вы получаете указатель на «весь» файл, как если бы он был в памяти.

Однако на этом этапе ничего не произошло, кроме фактической операции сопоставления резервирования страниц для файла в виртуальной машине. (Большой файл, тем длиннее операция отображения, конечно.)

Чтобы начать считывать данные из файла, вы просто получаете к нему доступ через указатель, который вы вернули в вызове mmap.

Если вы хотите «предварительно загрузить» части файла, просто зайдите в область, которую вы хотите предварительно загрузить. Убедитесь, что вы посещаете ВСЕ страницы, которые хотите загрузить, поскольку виртуальная машина загружает только страницы, к которым вы обращаетесь. Например, скажем, в вашем 1G-файле у вас есть 10-мегабайтная «индексная» область, на которую вы хотели бы отобразить. Самый простой способ - просто «прогуливать свой индекс» или любую имеющуюся у вас структуру данных, позволяя странице VM при необходимости. Или, если вы «знаете», что это «первые 10 МБ» файла, и что размер вашей страницы для вашей виртуальной машины составляет, скажем, 4K, тогда вы можете просто нанести указатель mmap на указатель символа и просто перебрать страницы.

void load_mmap(char *mmapPtr) { 
    // We'll load 10MB of data from mmap 
    int offset = 0; 
    for(int offset = 0; offset < 10 * 1024 * 1024; offset += 4 * 1024) { 
     char *p = mmapPtr + offset; 
     // deref pointer to force mmap load 
     char c = *p; 
    } 
} 

Что касается L1 и L2 кэшей, ММАП не имеет ничего общего с тем, что это все о том, как получить доступ к данным.

Поскольку вы используете базовую систему VM, все, что обращается к данным в блоке mmap'd, будет работать (когда-либо с сборки).

Если вы не изменяете данные mmap'd, виртуальная машина автоматически удалит старые страницы с новыми страницами. Если вы действительно измените их, VM вернет вам эти страницы.

+8

Не будет обугливается "с = * р" быть оптимизированы прочь? Должен ли c быть объявлен изменчивым? –

+1

В последних версиях Linux вы можете установить MAP_POPULATE в аргументе flags в mmap(), и страницы будут вытащены до того, как будет возвращен вызов. Это блокирует вызов в течение определенного периода времени, который является некоторой функцией размера файла, поэтому запуск функции load_mmap() в отдельном потоке может повысить производительность, если есть другая работа, которая может выполняться параллельно, прежде чем содержимое файла потребуется для чтения, тем более, что большая часть работы выполняется на стороне ядра. –

+0

Разве «mlock» не загружает страницы? –

3

Это не связано с кэшами процессора; он отображает его в виртуальное адресное пространство, и если он впоследствии будет доступен или заблокирован с помощью mlock(), он физически выводит его в память. Какой процессор кэширует его или нет, вы ничего не контролируете (по крайней мере, не через mmap).

Обычно прикосновение к страницам необходимо для его отображения, но если вы используете mlock или mlockall, это будет иметь тот же эффект (обычно это привилегия).

Что касается накладных расходов, я действительно не знаю, вам придется его измерять. Я предполагаю, что mmap(), который не загружает страницы, является более или менее постоянной операцией времени, но при этом страницы будут занимать больше времени с большим количеством страниц.

Последние версии Linux также поддерживает MAP_POPULATE флаг, который инструктирует ММАП для загрузки страниц сразу (предположительно, только если это возможно)

2

Отвечая на вопрос г-Рави Phulsundar в:

Несколько процессов могут отображать один и тот же файл если разрешения установлены правильно. Глядя на странице ММАП человек просто передать MAP_SHARED флаг (если необходимо отобразить действительно большой файл использовать mmap2 вместо этого):

mmap

MAP_SHARED

Доля этого отображения со всеми другими процессами, Нарисуйте этот объект. Хранение в этом регионе эквивалентно записи в файл. Файл может не обновляться до тех пор, пока не вызовутся msync (2) или munmap (2).

Смежные вопросы