Помимо 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.
В Linux существует два разных, но равноценных способа создания анонимного отображения с помощью вызова mmap().
• Указать значение MAP_ANONYMOUS для аргумента flags и -1 для аргумента fd (в Linux при использовании данного флага значение аргумента fd игнорируется; но некоторые разновидности UNIX требуют, чтобы в этом случае аргумент fd был равен -1 — портируемые приложения должны поступать именно так).
Для получения определения MAP_ANONYMOUS из заголовочного файла
• Открыть файл устройства /dev/zero и передать полученный дескриптор вызову mmap().
/dev/zero представляет собой виртуальное устройство, при чтении из которого всегда возвращаются нули. Запись в него всегда отклоняется. Обычно /dev/zero применяется для заполнения файла нулями (например, с помощью команды dd(1)).
При использовании любой из этих методик содержимое итогового отображения заполняются нулями, а аргумент offset игнорируется (так как нет исходного файла, для которого можно было бы указать отступ). Примеры применения обоих подходов будут показаны чуть ниже.