Читать «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)