Главная страница Взаимодействие нетривиальных процессов Мы показали, что у родительского и дочернего процессов имеются собственные копии указателя ptr, но обе копии указывают на одну и ту же область памяти - счетчик, увеличиваемый обоими процессами. Изменим программу в листинге 12.2 так, чтобы использовались семафоры Posix, размещаемые в памяти (вместо именованных). Разместим такой семафор в разделяемой области памяти. Новая программа приведена в листинге 12.3. Листинг 12.3. Счетчик и семафор размещены в разделяемой памяти shm/incr3.c 1 finclude unpipc.h 2 struct shared { 3 setti t mutex: /* взаимное исключение; семафор, размещаемый в памяти */ 4 int count; /* и счетчик */ 5 } shared; 6 int 7 mainCint argc, char **argv) 9 int fd, i, nloop: 10 struct shared *ptr; 11 if (argc != 3) 12 err quit( usage: incr3 <pathname> <floops> ): 13 nloop = atoi(argv[2]); 14 /* открываем файл, инициализируем нулем, отображаем в память */ 15 fd - Open(argv[l]. 0 ROWR 0 CREAT. FILE f )E); 16 Write(fd. &shared. sizeof(struct shared)); 17 ptr - Mmap(NULL. sizeof(struct shared). PROT READ PROT WRITE, 18 MAP SHAREO, fd, 0): 19 Close(fd); 20 /* инициализация семафора, совместно используемого процессами */ 21 Sem init(&ptr->mutex, 1, 1): 22 setbuf(stdout, NULL); /* stdout не буферизуется */ 23 if (ForkO =- 0) { /* дочерний процесс */ 24 for (i - 0; i < nloop; i++) { 25 Sem wait(&ptr->mutex); 26 printf( child: *d\n , ptr->count++); 27 Sem post(&pt r->mutex); 28 } 29 exit(O); 30 } 31 /* родительский процесс */ 32 for (i = 0: i < nloop: i++) { 33 Sem wait(&ptr->mutex); 34 printf( parent: *d\n , ptr->count++); 35 Sem post(&ptr->mutex); 36 } 37 exit(O); 38 } Определение структуры, хранящейся в разделяемой памяти 2-5 Помещаем целочисленный счетчик и семафор, защищающий его, в одну структуру. Эта структура будет храниться в разделяемой памяти. Отображаем в память 14-19 Создается файл для отображения в память, который инициализируется структурой с нулевым значением обоих полей. При этом инициализируется только счетчик, поскольку семафор будет инициализирован позднее вызовом sem init. Тем не менее проще инициализировать всю струетуру нулями, чем только одно целочисленное поле. Инициализация семафора 20-21 Используем семафор, размещаемый в памяти, вместо именованного. Для его инициализации единицей вызываем sem init. Второй аргумент должен быть ненулевым, чтобы семафор мог совместно использоваться несколькими процессами. На рис. 12.7 изображена модификация рис. 12.6, где семафор переместился из ядра в разделяемую память. разделяемая память счетчик и семафор родительский процесс выполняется эта команда родительского процесса struct shared *ptr; if(Fork()==0) { Л child */ } Г parent */ дочерний процесс выполняется эта команда - дочернего процесса struct shared *ptr; if(Fork()==0) { Л child */ /* parent */ Рис. 12.7. И семафор, и счетчик теперь хранятся в разделяемой памяти 12.4. Неименованное отображение в память в 4.4BSD Наши примеры из листингов 12.2 и 12.3 работают отлично, но нам приходится создавать файл в файловой системе (аргумент командной строки), вызывать open, записывать нули в файл вызовом write (чтобы проинициализировать его). Если mmap используется для передачи области разделяемой памяти через fork, мы можем упростить эту схему, используя свойства реализации. 1. В версии 4.4BSD предоставляется возможность неименованного отображения в память. При этом полностью пропадает необходимость создавать или от- крывать файлы. Вместо этого указываются флаги MAP SHARED MAP ANON и дескриптор fd = -1. Сдвиг, задаваемый аргументом offset, игнорируется. Память автоматически инициализируется нулями. Пример использования приведен в листинге 12.4. 2. В версии SVR4 имеется файл /dev/zero, который мы открываем и дескриптор которого указываем при вызове mmap. Это устройство возвращает нули при попытке считывания, а весь направляемый на него вывод сбрасывается. Пример использования приведен в листинге 12.5. (Во многих реализациях, про-изощедщих от BSD, также поддерживается устройство /dev/zero, например в SunOS 4.1.x и BSD/OS 3.1.) В листинге 12.4 приведена часть листинга 12.2, которая изменяется при переходе к использованию неименованного отображения в память в 4.4BSD. Листинг 12.4. Отображение в память в 4.4BSD shtti/i ncr ttiap anon. с 3 int 4 mainCint argc, char **argv) 6 int i. nloop: 7 int *ptr: 8 sem t *mutex: 9 if (argc != 2) 10 err quit( usage: incr map anon <#loops> ): 11 nloop = atoi(argv[l]): 12 /* отображение в память */ 13 ptr - Mmap(NULL. sizeof(int), PROT REAO PROT WRITE. 14 MAP SHARED MAP ANON. -1. 0): 6-11 Автоматические переменные fd и zero больше не используются, как и аргумент командной строки, задававший имя создаваемого файла. 12-14 Файл больше не нужно открывать. Вместо этого указывается флаг MAP ANON при вызове mmap, а пятый аргумент этой функции (дескриптор) принимает значение -1. 12.5. Отображение в память в SVR4 с помощью /dev/zero в листинге 12.5 приведена часть новой версии программы, претерпевшая изменения по сравнению с листингом 12.2 при переходе к использованию отображения с помощью /dev/zero. Листинг 12.5. Отображение памяти в SVR4 с помощью /dev/zero shm/incr dev zero.c 3 int 4 main(int argc, char **argv) 6 int fd. i. nloop: 7 int *ptr: 8 sem t *mutex: продолжение-6
|
© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |