![]() |
![]() |
Главная страница Взаимодействие нетривиальных процессов входной файл входной файл файл считывающий поток О - входной 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: /* кольцевой буфер */ продолжение ё>-
|
© 2000 - 2025 ULTRASONEX-AMFODENT.RU.
Копирование материалов разрешено исключительно при условии цититирования. |