Читать «UNIX: взаимодействие процессов» онлайн - страница 321
Уильям Ричард Стивенс
Листинг А.31. Выделение разделяемой памяти под родительский и дочерние процессы
//lib/my_shm.c
1 #include "unpipc.h"
2 void *
3 my_shm(size_t nbytes)
4 {
5 void *shared;
6 #if defined(MAP_ANON)
7 shared = mmap(NULL, nbytes, PROT_READ | PROT_WRITE,
8 MAP_ANON | MAP_SHARED, –1, 0);
9 #elif defined(HAVE_DEV_ZERO)
10 int fd;
11 /* отображение в память файла /dev/zero */
12 if ((fd = open("/dev/zero", O_RDWR)) == –1)
13 return(MAP_FAILED);
14 shared = mmap(NULL, nbytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
15 close(fd);
16 #else
17 # error cannot determine what type of anonymous shared memory to use
18 #endif
19 return(shared); /* ошибка отображения в память */
20 }
Если система поддерживает флаг MAP_ANON (раздел 12.4), мы используем этот тип разделяемой памяти. В противном случае используется отображение в память файла /dev/zero (раздел 12.5).
Последующие изменения зависят от средства синхронизации и от того, что происходит с лежащим в основе этого средства типом данных при вызове fork. Детали описаны в разделе 10.12.
■ Взаимное исключение Posix: должно храниться в разделяемой памяти (вместе со счетчиком) и инициализироваться с установленным атрибутом PTHREAD_ PROCESS_SHARED. Код программы будет приведен ниже.
■ Блокировка чтения-записи Posix: должна храниться в разделяемой памяти (вместе со счетчиком) и инициализироваться с установленным атрибутом PTHREAD_PROCESS_SHARED.
■ Семафоры Posix, размещаемые в памяти: семафор должен храниться в разделяемой памяти (вместе со счетчиком), и вторым аргументом при вызове sem_init должна быть единица (указывающая на то, что семафор используется несколькими процессами).
■ Именованные семафоры Posix: следует либо вызывать sem_open из родительского и дочерних процессов по отдельности, либо вызывать sem_open в родительском процессе, учитывая, что семафор станет общим после вызова fork.
■ Семафоры System V: никакого специального кодирования не требуется, поскольку эти семафоры всегда могут использоваться как процессами, так и потоками. Дочерним процессам достаточно знать идентификатор семафора.
■ Блокировка записей fcntl: изначально предназначена для использования несколькими процессами.
Мы приведем код только для программы с взаимными исключениями Posix.
Взаимные исключения Posix между процессами
Функция main первой программы использует взаимное исключение Posix для обеспечения синхронизации. Текст ее приведен в листинге А.32.
Листинг А.32. Функция main для измерения быстродействия взаимных исключений между процессами
//bench/incr_pmutex5.с
1 #include "unpipc.h"
2 #define MAXNPROC 100
3 int nloop;
4 struct shared {
5 pthread_mutex_t mutex;
6 long counter;
7 } *shared; /* указатель, сама структура в общей памяти */
8 void *incr(void *);
9 int
10 main(int argc, char **argv)
11 {
12 int i, nprocs;
13 pid_t childpid[MAXNPROC];
14 pthread_mutexattr_t mattr;
15 if (argc != 3)