Главная страница  Взаимодействие нетривиальных процессов 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 [ 165 ] 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

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

А.6. Синхронизация процессов: программы

в программах предыдущего раздела счетчик использовался несколькими потоками одного процесса. При этом он представлял собой глобальную переменную. Теперь нам нужно изменить эти программы для измерения скорости синхронизации различных процессов.

Для разделения счетчика между родительским процессом и дочерними мы помещаем его в разделяемую память, выделяемую функцией my shm, показанной в листинге А.31.

Листинг А.31. Выделение разделяемой памяти под родительский и дочерние процессы

lib/my shm.c

1 #include unpipc.h

2 void *

3 my shm(size t nbytes)

5 void *shared;

6 #if definedCMAP ANON)

7 shared = mmapCNULL. nbytes, PROTJEAD PROT WRITE,

8 MAP ANON I MAPJHARED. -1. 0);

9 #elif defined(HAVEJEVJERO)

10 int fd;

11 /* отображение в память файла /dev/zero */

12 if ( (fd = open( /dev/zero , OJDWR)) == -1)

13 returnCMAP FAILED);

14 shared = mmapCNULL, nbytes. PROTJEAD PROTJRITE, MAPJHARED, fd, 0);

15 CloseCfd);

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 SHAREO. Код программы будет приведен ниже.

ш Блокировка чтения-записи Posix: должна храниться в разделяемой памяти (вместе со счетчиком) и инициализироваться с установленным атрибутом PTHREAO PROCESS SHARED.

ii Семафоры Posix, размещаемые в памяти: семафор должен храниться в разделяемой памяти (вместе со счетчиком), и вторым аргументом при вызове sem i nit должна быть единица (указывающая на то, что семафор используется несколькими процессами).

* Именованные семафоры Posix: следует либо вызывать sem open из родительского и дочерних процессов по отдельности, либо вызывать semopen в родительском процессе, учитывая, что семафор станет общим после вызова fork.

ii Семафоры System V: никакого специального кодирования не требуется, поскольку эти семафоры всегда могут использоваться как процессами, так и потоками. Дочерним процессам достаточно знать идентификатор семафора.

ii Блокировка записей fcntl: изначально предназначена для использования несколькими процессами.

Мы приведем код только для программы с взаимными исключениями Posix.

Взаимные ис1а1ючения Posix между процессами

Функция main первой программы использует взаимное исключение Posix для обеспечения синхронизации. Текст ее приведен в листинге А.32.

Листинг А.32. Функция main для измерения быстродействия взаимных исключений между процессами

bench/incr pmutex5.c

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 mainCint argc. char **argv)

11 {

12 int i. nprocs:

13 pid t childpid[MAXNPROC]:

14 pthread mutexattr t mattr;

15 if (argc != 3)

16 err quit( usage: incr pxmutex5 <#loops><#processes> ); продолжение



Листинг А.32 (продолжение)

17 nloop - atoi(argv[l]):

18 nprocs = min(atoi(argv[2]). MAXNPROC);

19 /* получение разделяемой памяти для родительского и дочерних процессов */

20 shared = My shm(sizeofCstruct shared));

21 /* инициализация взаимного исключения и его блокировка */

22 Pthread mutexattrjnit(&mattr);

23 Pthread mutexattr setpshared(&mattr, PTHREAD PROCESS SHARED);

24 Pthread mutexjnit(&shared->niutex. &mattr);

25 Pthread mutexattr destroy(&mattr):

26 Pthread mutexJock(&shared->niutex);

27 /* порождение дочерних процессов */

28 for (i = 0; i < nprocs; i++) {

29 if ( (childpid[i] = ForkO) == 0) {

30 incr(NULL):

31 exitCO);

32 }

33 }

34 /* родительский процесс; запуск таймера и разблокирование взаимного

исключения */

35 StartJimeO;

36 Pthread mutex unlock(&shared->mutex);

37 /* ожидание завершения всех дочерних процессов */

38 for (i = 0; i < nprocs; i++) {

39 Waitpid(childpid[i]. NULL, 0);

40 }

41 printfCmicroseconds; .Of usec\n , Stop time());

42 if (shared->counter != nloop * nprocs)

43 printfCerror; counter = ld\n . shared->counter);

44 exitCO):

45 }

19-20 Поскольку мы запускаем несколько процессов, структура shared должна располагаться в разделяемой памяти. Мы вызываем функцию my shm, текст которой приведен в листинге А.З!,

21-26 Поскольку взаимное исключение помещено в разделяемую память, мы не можем статически инициализировать его, поэтому мы вызываем pthread mutex i nit после установки атрибута PTHREAD PROCESS SHARED. Взаимное исключение блокируется,

27-36 После создания дочерних процессов и запуска таймера блокировка снимается.

37-43 Родительский процесс ожидает заверщения всех дочерних, после чего останавливает таймер.

Листинг А.ЗЗ. Увеличение счетчика с использованием взаимных исключений между процессами

bench/iПСr pxmutex5.с

46 void *

47 incrCvoid *arg)



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 [ 165 ] 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186

© 2000 - 2024 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования.