12.3. Увеличение счетчика в отображаемом в память файле

12.3. Увеличение счетчика в отображаемом в память файле

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

Листинг 12.2. Родительский и дочерний процессы увеличивают значение счетчика в разделяемой памяти

//shm/incr2.c

1  #include "unpipc.h"

2  #define SEM_NAME "mysem"

3  int

4  main(int argc, char **argv)

5  {

6   int fd, i, nloop, zero = 0;

7   int *ptr;

8   sem_t *mutex;

9   if (argc != 3)

10   err_quit("usage: incr2 <pathname> <#loops>");

11  nloop = atoi(argv[2]);

12  /* открываем файл, инициализируем нулем и отображаем в память */

13  fd = Open(argv[1], O_RDWR | O_CREAT, FILE_MODE);

14  Write(fd, &zero, sizeof(int));

15  ptr = Mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

16  Close(fd);

17  /* создаем, инициализируем и отключаем семафор */

18  mutex = Sem_open(Px_ipc_name(SEM_NAME), O_CREAT | O_EXCL, FILE_MODE, 1);

19  Sem_unlink(Px_ipc_name(SEM_NAME));

20  setbuf(stdout, NULL); /* stdout не буферизуется */

21  if (Fork() == 0) { /* дочерний процесс */

22   for (i = 0; i < nloop; i++) {

23    Sem_wait(mutex);

24    printf("child: %d ", (*ptr)++);

25    Sem_post(mutex);

26   }

27   exit(0);

28  }

29  /* родительский процесс */

30  for (i = 0; i < nloop; i++) {

31   Sem_wait(mutex);

32   printf("parent: %d ", (*ptr)++);

33   Sem_post(mutex);

34  }

35  exit(0);

36 }

Новый аргумент командной строки

11-14 Из командной строки теперь считывается еще один аргумент, задающий полное имя файла, который будет отображен в память. Мы открываем файл для чтения и записи, причем если файл не существует, он будет создан, а затем инициализируем файл нулем.

Вызов mmap и закрытие дескриптора

15-16 Вызов mmap позволяет отобразить открытый файл в адресное пространство процесса. Первый аргумент является нулевым указателем, при этом система сама выбирает адрес начала отображаемого сегмента. Длина файла совпадает с размером целого числа. Устанавливается доступ на чтение и запись. Четвертый аргумент имеет значение MAP_SHARED, что позволяет процессам «видеть» изменения, вносимые друг другом. Функция возвращает адрес начала участка разделяемой памяти, мы сохраняем его в переменной ptr.

fork

20-34 Мы отключаем буферизацию стандартного потока вывода и вызываем fork. И родительский, и дочерний процессы по очереди увеличивают значение целого, на которое указывает ptr.

Отображенные в память файлы обрабатываются при вызове fork специфическим образом в том смысле, что созданные родительским процессом отображения наследуются дочерним процессом. Следовательно, открыв файл и вызвав mmap с флагом MAP_SHARED, мы получили область памяти, совместно используемую родительским и дочерним процессами. Более того, поскольку эта общая область на самом деле представляет собой отображенный файл, все изменения, вносимые в нее (область памяти, на которую указывает ptr, — размером sizeof (int)), также действуют и на содержимое реального файла (имя которого было указано в командной строке).

Запустив эту программу на выполнение, мы увидим, что память, на которую указывает ptr, действительно используется совместно родительским и дочерним процессами. Приведем значения счетчика перед переключением процессов:

solaris % incr2 /tmp/temp.110000

child: 0     запускается дочерний процесс

child: 1

child: 128

child: 129

parent: 130  дочерний процесс приостанавливается, запускается родительский процесс

parent: 131

parent: 636

parent: 637

child: 638   родительский процесс приостанавливается, запускается дочерний процесс

child: 639

child: 1517

child: 1518

parent: 1519 дочерний процесс приостанавливается, запускается родительский процесс

parent: 1520

parent: 19999 последняя строка вывода

solaris % od –D /tmp/temp.1

0000000 0000020000

0000004

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

На рис. 12.6 изображена схема, отличающаяся от рис. 12.4. Здесь используется разделяемая память и показано, что семафор также используется совместно. Семафор мы изобразили размещенным в ядре, но для семафоров Posix это не обязательно. В зависимости от реализации семафор может обладать различной живучестью, но она должна быть по крайней мере не меньше живучести ядра. Семафор может быть реализован также через отображение файла в память, что мы продемонстрировали в разделе 10.15. 

Рис. 12.6. Родительский и дочерний процессы используют разделяемую память и общий семафор 

Мы показали, что у родительского и дочернего процессов имеются собственные копии указателя ptr, но обе копии указывают на одну и ту же область памяти — счетчик, увеличиваемый обоими процессами.

Изменим программу в листинге 12.2 так, чтобы использовались семафоры Posix, размещаемые в памяти (вместо именованных). Разместим такой семафор в разделяемой области памяти. Новая программа приведена в листинге 12.3.

Листинг 12.3. Счетчик и семафор размещены в разделяемой памяти

//shm/incr3.c

1  #include "unpipc.h"

2  struct shared {

3   sem_t mutex; /* взаимное исключение: семафор, размещаемый в памяти */

4   int count; /* и счетчик */

5  } shared;

6  int

7  main(int argc, char **argv)

8  {

9   int fd, i, nloop;

10  struct shared *ptr;

11  if (argc != 3)

12   err_quit("usage: incr3 <pathname> <#loops>");

13  nloop = atoi(argv[2]);

14  /* открываем файл, инициализируем нулем, отображаем в память */

15  fd = Open(argv[1], O_RDWR | O_CREAT, FILE_MODE);

16  Write(fd, &shared, sizeof(struct shared));

17  ptr = Mmap(NULL, sizeof(struct shared), PROT_READ | PROT_WRITE,

18   MAP_SHARED, fd, 0);

19  Close(fd);

20  /* инициализация семафора, совместно используемого процессами */

21  Sem_init(&ptr->mutex, 1, 1);

22  setbuf(stdout, NULL); /* stdout не буферизуется */

23  if (Fork() == 0) { /* дочерний процесс */

24   for (i = 0; i < nloop; i++) {

25    Sem_wait(&ptr->mutex);

26    printf("child: %d ", ptr->count++);

27    Sem_post(&ptr->mutex);

28   }

29   exit(0);

30  }

31  /* родительский процесс */

32  for (i = 0; i < nloop; i++) {

33   Sem_wait(&ptr->mutex);

34   printf("parent: %d ", ptr->count++);

35   Sem_post(&ptr->mutex);

36  }

37  exit(0);

38 } 

Определение структуры, хранящейся в разделяемой памяти

2-5 Помещаем целочисленный счетчик и семафор, защищающий его, в одну структуру. Эта структура будет храниться в разделяемой памяти.

Отображаем в память

14-19 Создается файл для отображения в память, который инициализируется структурой с нулевым значением обоих полей. При этом инициализируется только счетчик, поскольку семафор будет инициализирован позднее вызовом sem_init. Тем не менее проще инициализировать всю структуру нулями, чем только одно целочисленное поле.

Инициализация семафора

20-21 Используем семафор, размещаемый в памяти, вместо именованного. Для его инициализации единицей вызываем sem_init. Второй аргумент должен быть ненулевым, чтобы семафор мог совместно использоваться несколькими процессами.

На рис. 12.7 изображена модификация рис. 12.6, где семафор переместился из ядра в разделяемую память. 

Рис. 12.7. И семафор, и счетчик теперь хранятся в разделяемой памяти

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

3.2.3 Увеличение и уменьшение*

Из книги C++ автора Хилл Мюррей

3.2.3 Увеличение и уменьшение* – * Следовало бы переводить как «инкремент» и «декремент», однако мы следовали терминологии, принятой в переводной литратуре по C, поскольку эти операции унаследованы от C. (прим.перев.)Операция ++ используется для явного выражения приращения


7.2.1 Увеличение и Уменьшение

Из книги Интернет-разведка [Руководство к действию] автора Ющук Евгений Леонидович

7.2.1 Увеличение и Уменьшение Операнд префиксного ++ получает приращение. Операнд дожен быть адресным . Значением является новое значение операда, но оно не адресное. Выражение ++x эквивалентно x+=1. По поводу данных о преобразованиях см. обсуждение операций слжения (#7.4) и


Просмотр счетчика посещений сайта

Из книги AutoCAD 2009 для студента. Самоучитель автора Соколова Татьяна Юрьевна

Просмотр счетчика посещений сайта Неочевидный для многих, но иногда крайне полезный ресурс при изучении сайта компании – счетчик посещений этого сайта. Он позволяет отслеживать, сколько посетителей и откуда приходят на сайт, а также участвовать в рейтингах.Счетчик


Увеличение объектов

Из книги UNIX: взаимодействие процессов автора Стивенс Уильям Ричард

Увеличение объектов Команда LENGTHEN, которая осуществляет увеличение объектов, вызывается из падающего меню Modify ? Lengthen.Действие команды LENGTHEN не распространяется на замкнутые объекты.Запросы команды LENGTHEN: Select an object or [DElta/Percent/Total/DYnamic]: – выбрать объект или один из ключей Current


13.5. Увеличение общего счетчика

Из книги Системное программирование в среде Windows автора Харт Джонсон М

13.5. Увеличение общего счетчика Разработаем программу, аналогичную приведенной в разделе 12.3, — несколько процессов увеличивают счетчик, хранящийся в разделяемой памяти. Итак, мы помещаем счетчик в разделяемую память, а для синхронизации доступа к нему используем


Настройка спин-счетчика

Из книги Визуальное моделирование электронных схем в PSPICE автора Хайнеманн Роберт

Настройка спин-счетчика Обычно, если в результате выполнения функции EnterCriticalSection поток обнаруживает, что объект CS уже принадлежит другому потоку, он входит в ядро и остается блокированным до тех пор, пока не освободится объект CRITICAL_SECTION, что требует определенного времени.


6.5. Увеличение фрагментов диаграмм

Из книги Первые шаги с Windows 7. Руководство для начинающих автора Колисниченко Денис Н.

6.5. Увеличение фрагментов диаграмм С одним из методов создания в PROBE увеличенных фрагментов диаграмм вы уже познакомились: с помощью окон X Axis Settings и Y Axis Settings вы можете увеличить любой интересующий вас фрагмент до размеров всей рабочей поверхности экрана. Помимо этого, в


6.5. Увеличение производительности NTFS

Из книги Инфобизнес на полную мощность [Удвоение продаж] автора Парабеллум Андрей Алексеевич

6.5. Увеличение производительности NTFS Можно долго спорить о том, какая файловая система лучше — FAT32 или NTFS. С моей точки зрения — однозначно NTFS. Она обеспечивает должный уровень безопасности и предоставляет возможности, которые не доступны в FAT32, кроме того, она


Увеличение цены

Из книги AutoCAD 2009. Учебный курс автора Соколова Татьяна Юрьевна


Увеличение ценности

Из книги AutoCAD 2008 для студента: популярный самоучитель автора Соколова Татьяна Юрьевна


Увеличение объектов

Из книги Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ автора Борри Хелен

Увеличение объектов Команда LENGTHEN , которая осуществляет увеличение объектов, вызывается из падающего меню Modify ? Lengthen.Действие команды LENGTHEN не распространяется на замкнутые объекты.Запросы команды


Увеличение объектов

Из книги Adobe Flash. Создание аркад, головоломок и других игр с помощью ActionScript автора Розенцвейг Гэри

Увеличение объектов Команда LENGTHEN, которая осуществляет увеличение объектов, вызывается из падающего меню Modify ? Lengthen.Действие команды LENGTHEN не распространяется на замкнутые объекты.Запросы команды lengthen: Select an object or [DElta/Percent/Total/DYnamic]: – выбрать объект или один из ключейCurrent


Установки в файле конфигурации

Из книги Linux программирование в примерах автора Роббинс Арнольд

Установки в файле конфигурации Файл конфигурации Firebird, как обсуждалось ранее в этой главе, дает возможность выполнить установки по ограничению доступа к библиотекам внешних функций, модулей фильтров BLOB и К файлам данных, связанных с таблицами с помощью определения CREATE


Увеличение кнопок

Из книги UNIX — универсальная среда программирования автора Пайк Роб

Увеличение кнопок Исходный файл: Expandingbuttons.fla Многие сайты используют Flash для навигации от страницы к странице. Даже простой Flash-ролик с одной кнопкой может значительно оживить статическую Web-страницу. При помощи ActionScript вы сможете сделать эти кнопки анимированными.Задача


2.2 Что хранится в файле?

Из книги автора

2.2 Что хранится в файле? Формат файла зависит от программ, которые используют его. Типы файла весьма разнообразны, возможно, потому, что существует большое разнообразие программ. Но, поскольку типы файла не определяются файловой системой, ядро не может указать вам тип