Помимо MAP_PRIVATE и MAP_SHARED, аргумент flags вызова mmap() в Linux поддерживает ряд других значений (которые можно перечислять через побитовое ИЛИ). Все они собраны в табл. 45.3. Из них только MAP_FIXED входит в стандарт SUSv3 (вместе с MAP_PRIVATE и MAP_SHARED).

Таблица 45.3. Значения битовой маски для аргумента flags вызова mmap()

Значение — Описание — SUSv3

MAP_ANONYMOUS — Создает анонимное отображение —

MAP_FIXED — Не округляет аргумент addr (см. раздел 45.10) — *

MAP_LOCKED — Блокирует отображенные страницы в памяти (начиная с Linux 2.6) —

MAP_HUGETLB — Создает отображение, которое использует большие страницы (начиная с Linux 2.6.32) —

MAP_NORESERVE — Управляет резервированием пространства файла подкачки (см. раздел 45.9) —

MAP_PRIVATE — Изменения, вносимые в отображенные данные, являются приватными — *

MAP_POPULATE — Заполняет страницы отображения (начиная с Linux 2.6) —

MAP_SHARED — Изменения отображенных данных доступны другим процессам и возвращаются обратно в исходный файл (противоположность флагу MAP_PRIVATE) — *

MAP_UNINITIALIZED — Не очищает анонимные отображения (начиная с Linux 2.6.33) —

В следующем списке перечислены подробности о значениях аргумента flags из табл. 45.3 (за исключением MAP_PRIVATE и MAP_SHARED, которые уже были рассмотрены):

• MAP_ANONYMOUS — создает анонимное отображение — то есть не связанное с файлом. Этот флаг будет подробно описан в разделе 45.7;

• MAP_FIXED — об этом флаге рассказывается в разделе 45.10;

• MAP_HUGETLB (начиная с Linux 2.6.32) — имеет такое же назначение для вызова mmap(), как и флаг SHM_HUGETLB для сегментов разделяемой памяти в System V;

• MAP_LOCKED (начиная с Linux 2.6) — выполняет предварительную загрузку и блокирует отображенные страницы в памяти; похоже на действие вызова mlock(). Привилегии, необходимые для использования этого флага, а также ограничения, налагаемые на его работу, будут описаны в разделе 46.2;

• MAP_NORESERVE — определяет, нужно ли выполнять предварительное резервирование пространства файла подкачки для отображения. Подробности см. в разделе 45.9;

• MAP_POPULATE (начиная с Linux 2.6) — заполняет страницы отображения. В случае с файловым отображением выполняется упреждающее чтение файла. Это значит, что последующие обращения к содержимому отображения не будут блокироваться сбоями страницы (если только в результате давления страницы памяти не успели сброситься на диск);

• MAP_UNINITIALIZED (начиная с Linux 2.6.33) — предотвращает заполнение нулями анонимного отображения. Это улучшает производительность, но несет в себе потенциальную угрозу безопасности, поскольку выделенные страницы могут содержать конфиденциальную информацию, оставленную предыдущим процессом. Таким образом, данный флаг предназначен для использования во встраиваемых платформах, где производительность имеет решающее значение, а вся система находится под управлением одного или нескольких приложений. Действует только в ядрах, сконфигурированных с параметром CONFIG_MMAP_ALLOW_UNINITIALIZED.

45.7. Анонимные отображения

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

MAP_ANONYMOUS и /dev/zero

В Linux существует два разных, но равноценных способа создания анонимного отображения с помощью вызова mmap().

• Указать значение MAP_ANONYMOUS для аргумента flags и -1 для аргумента fd (в Linux при использовании данного флага значение аргумента fd игнорируется; но некоторые разновидности UNIX требуют, чтобы в этом случае аргумент fd был равен -1 — портируемые приложения должны поступать именно так).

Для получения определения MAP_ANONYMOUS из заголовочного файла необходимо определить один из двух макросов проверки возможностей: _BSD_SOURCE или _SVID_SOURCE. В Linux для совместимости с рядом других UNIX-систем, в которых используются другие названия, в качестве синонима флага MAP_ANONYMOUS доступна константа MAP_ANON.

• Открыть файл устройства /dev/zero и передать полученный дескриптор вызову mmap().

/dev/zero представляет собой виртуальное устройство, при чтении из которого всегда возвращаются нули. Запись в него всегда отклоняется. Обычно /dev/zero применяется для заполнения файла нулями (например, с помощью команды dd(1)).

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

Перейти на страницу:

Похожие книги