Linux MMAP внутренности - PullRequest
23 голосов
/ 15 апреля 2009

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

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

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

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

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

Ответы [ 4 ]

29 голосов
/ 15 апреля 2009

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

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

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

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

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

Поскольку вы используете базовую систему виртуальных машин, все, что обращается к данным в блоке mmap, будет работать (даже с момента сборки).

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

3 голосов
/ 15 апреля 2009

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

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

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

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

2 голосов
/ 30 апреля 2009

Отвечая на вопрос г-на Рави Фулсундара:

Несколько процессов могут отображать один и тот же файл, если права доступа установлены правильно. Чтобы просмотреть справочную страницу mmap, просто пропустите флаг MAP_SHARED (если вам нужно отобразить действительно большой файл, используйте вместо него mmap2):

ММАП

MAP_SHARED

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

0 голосов
/ 17 ноября 2010

вы используете MAP_SHARED

...