Читаем Linux API. Исчерпывающее руководство полностью

Использование флага MAP_ANONYMOUS и файла /dev/zero не предусмотрено стандартом SUSv3, хотя большинство реализаций UNIX поддерживает обе методики. Причина существования разных подходов с одним и тем же результатом заключается в том, что один из них пришел из мира BSD (MAP_ANONYMOUS), а другой — из System V (/dev/zero).

Анонимные отображения типа MAP_PRIVATE

Анонимные отображения типа MAP_PRIVATE служат для выделения блоков памяти, принадлежащих только одному процессу и заполненных нулями. Чтобы создать такое отображение, можно воспользоваться файлом устройства /dev/zero:

fd = open("/dev/zero", O_RDWR);

if (fd == -1)

errExit("open");

addr = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);

if (addr == MAP_FAILED)

errExit("mmap");

Реализация вызова malloc(), входящая в библиотеку glibc, использует анонимные отображения типа MAP_PRIVATE для выделения блоков памяти, превышающих MMAP_THRESHOLD байт. Это позволяет эффективно уничтожать такие блоки (с помощью munmap()), если передать их вызову free() (таким образом снижается и вероятность фрагментации памяти при многократном выделении и уничтожении больших блоков). Константа MMAP_THRESHOLD по умолчанию равна 128 байтам, но данное значение можно откорректировать, задействуя библиотечную функцию mallopt().

Анонимные отображения типа MAP_SHARED

Анонимные отображения типа MAP_SHARED позволяют родственным процессам (например, родителю и потомку) работать с одним и тем же участком памяти, не используя связанный с ним отображенный файл.

Анонимные отображения типа MAP_SHARED доступны в Linux, начиная с версии 2.4.

Методика, которую мы применяли для отображений типа MAP_ANONYMOUS, подходит и для MAP_SHARED:

addr = mmap(NULL, length, PROT_READ | PROT_WRITE,

MAP_SHARED | MAP_ANONYMOUS, — 1, 0);

if (addr == MAP_FAILED)

errExit("mmap");

Если вслед за кодом, приведенным выше, выполнить вызов fork(), то новый дочерний процесс унаследует отображение и получит доступ к тому же участку памяти, что и родитель.

Пример программы

Программа, представленная в листинге 45.3, демонстрирует использование MAP_ANONYMOUS или файла /dev/zero (на выбор) для разделения отображенного участка между родительским и дочерним процессами. Выбор методики зависит от того, был ли определен макрос USE_MAP_ANON на этапе компиляции программы. Перед вызовом fork() родитель инициализирует разделяемый участок с помощью значения 1. Затем потомок инкрементирует это общее целое число и завершается; дождавшись завершения потомка, родитель выводит получившееся число. При выполнении данной программы мы увидим следующее:

$ ./anon_mmap

Child started, value = 1

In parent, value = 2

Листинг 45.3. Разделение анонимного отображения между родительским и дочерним процессами

mmap/anon_mmap.c

#ifdef USE_MAP_ANON

#define _BSD_SOURCE /* Получаем определение MAP_ANONYMOUS */

#endif

#include

#include

#include

#include "tlpi_hdr.h"

int

main(int argc, char *argv[])

{

int *addr; /* Указатель на общий участок памяти */

#ifdef USE_MAP_ANON /* Используем MAP_ANONYMOUS */

addr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,

MAP_SHARED | MAP_ANONYMOUS, — 1, 0);

if (addr == MAP_FAILED)

errExit("mmap");

#else /* Отображаем /dev/zero */

int fd;

fd = open("/dev/zero", O_RDWR);

if (fd == -1)

errExit("open");

addr = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

if (addr == MAP_FAILED)

errExit("mmap");

if (close(fd) == -1) /* Больше не нужен */

errExit("close");

#endif

*addr = 1; /* Инициализируем целое число на отображенном участке */

switch (fork()) { /* Родитель и потомок разделяет отображение */

case -1:

errExit("fork");

case 0: /* Потомок инкрементирует общее число и завершается */

printf("Child started, value = %d\n", *addr);

(*addr)++;

if (munmap(addr, sizeof(int)) == -1)

errExit("munmap");

exit(EXIT_SUCCESS);

default: /* Родитель ждет завершения потомка */

if (wait(NULL) == -1)

errExit("wait");

printf("In parent, value = %d\n", *addr);

if (munmap(addr, sizeof(int)) == -1)

errExit("munmap");

exit(EXIT_SUCCESS);

}

}

mmap/anon_mmap.c

45.8. Изменение отображенного участка памяти: mremap()

В большинстве UNIX-систем нельзя изменить местоположение и размер существующего отображения отображения. Однако Linux предоставляет (недоступный в других реализациях) вызов mremap(), который делает возможными такие изменения.

Аргументы old_address и old_size обозначают местоположение и размер существующего отображения, которое мы хотим расширить или уменьшить. Адрес, указанный в old_address, должен быть выровнен по странице; обычно это значение, возвращенное предыдущим вызовом mmap(). Новый запрашиваемый размер указывается с помощью аргумента new_size. Значения old_size и new_size округляются до следующего кратного размеру страницы памяти в системе.

#define _GNU_SOURCE

#include

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

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

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных