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

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

входной

файл

входной

файл

файл

считывающий поток О -

входной

10 -

11 -

12 -

13 -

14 -

15 -

16 -

17

18

19

20

21 -22 23 24 25 26 27 28 29 30 31 32 33

записывающий поток

)> read О

уведомление записывающего потока

буфер

> read ()

уведомление

записывающего

потока

write

буфер

уведомление считывающего потока

> readO

уведомление

записывающего

потока

write

буфер

уведомление считывающего потока

> read О

уведомление

записывающего

потока


write () <

уведомление считывающего потока

время

Рис. 10.15. Процесс с двойной буферизацией

- 9 -10 -11 -12

-14 -15 -16

-28 -29

-30 -31

-32 -33

время

выходной файл

выходной

файл

выходной файл



устройствами типа накопителей на магнитной ленте, которые функционируют быстрее, если данные записываются с максимально возможной скоростью (это называется потоковым режимом - streaming mode).

Интересно, что задача с двойной буферизацией представляет собой лишь частный случай общей задачи производителей и потребителей.

Изменим нашу программу так, чтобы использовать несколько буферов. Начнем с решения из листинга 10.11, в котором использовались размещаемые в памяти семафоры. Мы получим даже не двойную буферизацию, а работу с произвольным числом буферов (задается NBUFF). В листинге 10.18 даны глобальные переменные и функция main.

Листинг 10.18. Глобальные переменные и функция main

pxsem/mycat2.c

1 finclude unpipc.h

2 fdefine NBUFF 8

3 struct { /* общие данные */

4 struct {

5 char data[BUFFSIZE]: /* буфер */

6 ssize t n; /* объем буфера */

7 } buff[NBUFF]: /* количество буферов */

8 sem t mutex, nempty. nstored; /* семафоры, a не указатели */

9 } shared;

10 int fd: /* входной файл, копируемый в стандартный поток вывода */

11 void *produce(void *), *consuiTie(void *):

12 int

13 maindnt argc, char **argv)

14 {

15 pthread t tid produce, tid consume;

16 if (argc !- 2)

17 err quit( usage: mycat2 <pathname> );

18 fd - Open(argv[l], 0 RDONLY);

19 /* инициализация трех семафоров */

20 Sem init(&shared.mutex. 0, 1);

21 Sem init(&shared.nempty. 0, NBUFF);

22 Sem init(&shared.nstored. 0. 0):

23 /* один производитель, один потребитель */

24 Set concurrency(2):

25 Pthread create(&tid produce. NULL, produce, NULL): /* reader thread */

26 Pthread create(&tid consume. NULL, consume. NULL): /* writer thread */

27 PthreadJoin(tid produce. NULL):

28 Pthread join(tid consume, NULL);

29 Sem destroy(&shared.mutex):

30 . Sem destroy(&shared.nempty):

31 Sem destroy(&shared.nstored):



32 exit(O):

33 }

Объявление нескольких буферов

2-9 Структура shared содержит массив структур buff, которые состоят из буфера и его счетчика. Мы создаем NBUFF таких буферов.

Открытие входного файла

18 Аргумент командной строки интерпретируется как имя файла, который копируется в стандартный поток вывода.

В листинге 10.19 приведен текст функций produce и consume.

Листинг 10.19. Функции produce и consume

pxsem/mycat2.c

34 void *

35 produce(void *arg)

36 {

37 int i:

38 for (i - 0; ; ) {

39 Sem wait(&shared.nempty); /* Ожидание освобождения места в буфере */

40 Sem wait(&shared.mutex):

41 /* критическая область */

42 Sem post(&shared.mutex);

43 shared.buff[i].n - Read(fd, shared.buff[i].data. BUFFSIZE);

44 if (shared.buff[i].n - 0) {

45 Sem post(&shared.nstored); /* еще один объект */

46 return(NULL);

47 }

48 if (++i >= NBUFF)

49 i = 0; /* кольцевой буфер */

50 Sem post(&shared.nstored); /* еще один объект */

51 }

52 }

53 void *

54 consume(void *arg)

55 {

56 int i;

57 for (i - 0; ; ) {

58 Sem wait(&shared.nstored): /* ожидание появления объекта для обработки */

59 Sem wait(&shared.mutex):

60 /* критическая область */

61 Sem post(&shared.mutex);

62 if (shared.buff[i].n == 0)

63 return(NULL);

64 Write(STDOUT FILENO. shared.buff[i].data, shared.buff[i].n);

65 if (++i > N8UFF)

66 i - 0: /* кольцевой буфер */ продолжение ё>-



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