Скачиваний:
85
Добавлен:
12.05.2015
Размер:
913.92 Кб
Скачать

20.2. Функции mmap, munmap и msync

Функция mmapотображает файл в адресное пространство процесса. Мы используем эту функцию в следующих ситуациях:

  1. С обычными файлами для обеспечения ввода-вывода через отображение в память (раздел 19.3).

  2. Со специальными файлами для обеспечения неименованного отображения памяти (разделы 19.4 и 19.5).

#include <sys/mman.h>

void *mmap (void *addr, size_t len, int prot, int flags, int fd, off_t offset);

/* возвращает начальный адрес участка памяти в случае успешного завершения, MAP_FAILED – в случае ошибки */

Аргумент addrможет указывать начальный адрес участка памяти процесса, в который нужно отобразить содержимое дескриптораfd. Обычно ему присваивается значение нулевого указателя, что говорит ядру о необходимости выбрать начальный адрес самостоятельно. В любом случае функция возвращает начальный адрес сегмента памяти, выделенной для отображения.

Аргумент lenзадает длину отображаемого участка в байтах; участок может начинаться не с начала файла, а с некоторого места, задаваемого аргументомoffset. Обычноoffset=0. На рис.19.3изображена схема отображения файла в память.

рис. 19.3

Защита участка памяти с отображенным файлом обеспечивается с помощью аргумента protи констант, приведенных в табл.19.1. Обычное значение этого аргумента –PROT_READ | PROT_WRITE, что обеспечивает доступ на чтение и запись.

Таблица 19.1

Аргумент protдля вызоваmmap

prot

Описание

PROT_READ

Данные могут быть считаны

PROT_WRITE

Данные могут быть записаны

PROT_EXEC

Данные могут быть выполнены

PROT_NONE

Доступ к данным закрыт

Таблица 19.2

Аргумент flagдля вызоваmmap

flag

Описание

MAP_SHARED

Изменения передаются другим процессам

MAP_PRIVATE

Изменения не передаются другим процессам и не влияют на отображенный файл

MAP_FIXED

Аргумент addrинтерпретируется как адрес памяти

Аргумент flagsможет принимать значения из табл.19.2. Можно указать только один из флагов –MAP_SHAREDилиMAP_PRIVATE, прибавив к нему при необходимостиMAP_FIXED. Если указан флагMAP_PRIVATE, все изменения будут производиться только с образом файла в адресном пространстве процесса; другим процессам они доступны не будут. Если же указан флагMAP_SHARED, изменения отображаемых данных видны всем процессам, совместно использующим файл.

Одним из способов добиться совместного использования памяти родительским и дочерним процессами является вызов mmapс флагомMAP_SHAREDперед вызовомfork. Стандарт Posix.1 гарантирует в этом случае, что все отображения памяти, установленные родительским процессом, будут унаследованы дочерним. Более того, изменения в содержимом файла, вносимые родительским процессом, будут видны дочернему, и наоборот. Эту схему мы вскоре продемонстрируем в действии.

Для отключения отображения файла в адресное пространство процесса используется вызов munmap:

#include <sys/mman.h>

int munmap (void *addr, size_t len);

/* возвращает 0 в случае успешного завершения, -1 – в случае ошибки */

Аргумент addrдолжен содержать адрес, возвращенныйmmap, аlen– длину области отображения. После вызоваmunmapлюбые попытки обратиться к этой области памяти приведут к отправке процессу сигналаSIGSEGV(предполагается, что эта область памяти не будет снова отображена вызовомmmap).

Если область была отображена с флагом MAP_PRIVATE, все внесенные за время работы процесса изменения сбрасываются.

В изображенной на рис. 19.3схеме ядро обеспечивает синхронизацию содержимого файла, отображенного в память, с самой памятью при помощи алгоритма работы с виртуальной памятью (если сегмент был отображен с флагомMAP_SHARED). Если мы изменяем содержимое ячейки памяти, в которую отображен файл, через некоторое время содержимое файла будет соответствующим образом изменено ядром. Однако в некоторых случаях нам нужно, чтобы содержимое файла всегда было в соответствии с содержимым памяти. Тогда для осуществления моментальной синхронизации мы вызываемmsync:

#include <sys/mman.h>

int msync(void *addr, size_t len, int flags);

/* возвращает 0 в случае успешного завершения, -1 – в случае ошибки */

Аргумент flagsпредставляет собой комбинацию констант из табл.19.3.

Таблица 19.3

Значения аргумента flagsдля функцииmsync

Константа

Описание

MS_ASYNC

Осуществлять асинхронную запись

MS_SYNC

Осуществлять синхронную запись

MS_INVALIDATE

Сбросить кэш

Из двух констант MS_ASYNCиMS_SYNCуказать нужно одну и только одну. Отличие между ними в том, что возврат из функции при указании флагаMS_ASYNCпроисходит сразу же, как только данные для записи будут помещены в очередь ядром, а при указании флагаMS_SYNCвозврат происходит только после завершения операций записи. Если указан и флагMS_INVALIDATE, все копии файла, содержимое которых не совпадает с его текущим содержимым, считаются устаревшими. Последующие обращения к этим копиям приведут к считыванию данных из файла.

Почему вообще используется отображение в память? До сих пор мы всегда говорили об отображении в память содержимого файла, который сначала открывается вызовомopen, а затем отображается вызовомmmap. Удобство состоит в том, что все операции ввода-вывода осуществляются ядром и скрыты от программиста, а он просто пишет код, считывающий и записывающий данные в некоторую область памяти. Ему не приходится вызыватьread,writeилиlseek. Часто это заметно упрощает код.

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

Другой целью использования mmapможет являться разделение памяти между неродственными процессами. В этом случае содержимое файла становится начальным содержимым разделяемой памяти и любые изменения, вносимые в нее процессами, копируются обратно в файл (что дает этому виду IPC живучесть файловой системы). Предполагается, что при вызовеmmapуказывается флагMAP_SHARED, необходимый для разделения памяти между процессами.

Соседние файлы в папке Chapter.4