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

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

3 int nloop:

4 struct {

5 int semid;

6 long counter;

7 } shared;

8 struct sembuf postop, waitop;

9 void *incr(void *):

10 int

11 mainCint argc. char **argv)

12 {

13 int i. nthreads;

14 pthread t tid[MAXNTHREADS];

15 union semun arg;

16 if (argc != 3)

17 err quit( usage: incr svseml <#loops> <#threads>);

18 nloop = atoi(argv[l]);

19 nthreads = min(atoi(argv[2]), MAXNTHREADS):

20 /* создание семафора и инициализация его значением О */

21 shared.semid = Seniget(IPC PRIVATE, 1, IPCJREAT SVSEM MODE);

22 arg.val = 0;

23 Semctl(shared.semid. 0. SETVAL, arg):

24 postop.sem num = 0: /* инициализация двух структур semop */

25 postop.sem op = 1

26 postop.seffl flg = 0

27 waitop.sem num = 0

28 waitop.seffl op = -1;

29 waitop.sem flg = 0:

30 /* создание всех потоков */

31 Set concurrency(nthreads):

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

33 Pthread create(&tid[i]. NULL. incr. NULL);

34 }

35 /* запуск таймера и разблокирование семафора */

36 Start time():

37 Semop(shared.semid. &postop, 1); /* up by 1 */

38 /* ожидание завершения всех потоков */

39 for (i = 0; i < nthreads; i++) {

40 PthreadJoin(tid[i], NULL);

41 }

42 printf( microseconds: .Of usec\n . Stop time());

43 if (shared.counter != nloop * nthreads)

44 printf ( error: counter ld\n , shared, counter):

45 Semctl (shared, semid. 0. IPCJMID);

46 exit(O);

47 }



Листинг А.28. Увеличение общего счетчика с использованием семафоров System V

bench/incr svseml.c

48 void *

49 incrCvoid *arg)

50 {

51 int i;

52 for (i = 0: i < nloop; i++) {

53 SemopCshared.semid, &waitop. 1);

54 shared.counter++;

55 SemopCshared.semid. &postop. 1);

56 }

57 return(NULL):

58 }

20-23 Создается семафор с одним элементом, значение которого инициализируется нулем.

24-29 Инициализируются две структуры semop: одна для увеличения семафора, а другая для ожидания его изменения. Обратите внимание, что поле semf 1 g в обеих структурах имеет значение 0: флаг SEM UNDO не установлен.

Семафоры System V с флагом SEM UNDO

Единственное отличие от программы из листинга А.27 заключается в том, что поле sem flg структур semop устанавливается равным SEM UNDO, а не 0. Мы не приводим в книге новый листинг с этим небольшим изменением.

Блокировка записей fcntl

Последняя программа использует fcntl для синхронизации. Функция main приведена в листинге А.ЗО. Эта программа будет выполняться успешно только в том случае, если количество потоков равно 1, поскольку блокировка fcntl предназначена для использования между процессами, а не между потоками одного процесса. При указании нескольких потоков каждый из них всегда имеет возможность получить блокировку (то есть вызовы writew lock не приводят к остановке потока, потому что процесс уже является владельцем блокировки), и конечное значение счетчика оказывается неправильным.

Функция i пег, использующая блокировку записей, приведена в листинге А.29.

Листинг А.29. Увеличение общего счетчика с использованием блокировки записей fcntl

bench/incr fcntll.c

44 void *

45 incrCvoid *arg)

46 {

47 int i;

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

49 WritewJockCshared.fd, 0. SEEKJET, 0);

50 shared.counter++;

51 UnJock(shared.fd, 0, SEEKJET. 0):

52 }



53 return(NULL):

54 }

Листинг А.ЗО. Функция main для измерения производительности блокировки fcntl

bench/incr fcntll.c

4 #include unpipc.h

5 #define MAXNTHREADS 100

6 int nloop:

7 struct {

8 int fd;

9 long counter;

10 } shared;

11 void *incr(void *);

12 int

13 mainCint argc. char **argv)

14 {

15 int i. nthreads:

16 char *pathname;

17 pthread t tid[MAXNTHREADS]:

18 if (argc != 4)

19 err quit( usage: incr fcntll <pathname> <#loops> <#threads> ):

20 pathname = argv[l];

21 nloop = atoi(argv[2]);

22 nthreads = min(atoi(argv[3]). MAXNTHREADS);

23 /* создание файла и получение блокировки на запись */

24 shared.fd = Open (pathname, 0 RDWR OJREAT OJRUNC. FILE MODE);

25 WritewJock(shared.fd. 0. SEEKJET. 0);

26 /* создание всех потоков */

27 Set concurrency(nthreads);

28 for (i = 0: i < nthreads; i++) {

29 Pthread create(&tid[i]. NULL. incr. NULL):

30 }

31 /* запуск таймера и снятие блокировки на запись */

32 StartJimeO;

33 UnJоск(shared.fd. 0. SEEKJET, 0):

34 /* ожидание завершения всех потоков */

35 for (i = 0: i < nthreads; i++) {

36 PthreadJoin(tid[i], NULL);

37 }

38 pri ntf ( microseconds: .Of usec\n , StopJimeO);

39 if (shared.counter != nloop * nthreads)

40 printf( error: counter = Xld\n . shared,counter);

41 Unl ink(pathname);

42 exit(O);

43 }



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.
Копирование материалов разрешено исключительно при условии цититирования.