Вход/Регистрация
UNIX: взаимодействие процессов
вернуться

Стивенс Уильям Ричард

Шрифт:

27 Pthread_join(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(0);

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 >= NBUFF)

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

67 Sem_post(&shared.nempty); /* освободилось место для объекта */

68 }

69 }

Пустая критическая область

40-42 Критическая область, защищаемая семафором mutex, в данном примере пуста. Если бы буферы данных представляли собой связный список, здесь мы могли бы удалять буфер из списка, не конфликтуя при этом с производителем. Но в нашем примере, где мы просто переходим к следующему буферу с единственным потоком-производителем, защищать нам просто нечего. Тем не менее мы оставляем операции установки и снятия блокировки, подчеркивая, что они могут потребоваться в новых версиях кода.

Считывание данных и увеличение семафора nstored

43-49 Каждый раз, когда производитель получает пустой буфер, он вызывает функцию read. При возвращении из read увеличивается семафор nstored, уведомляя потребителя о том, что буфер готов. При возвращении функцией read значения 0 (конец файла) семафор увеличивается, а производитель завершает работу.

Поток-потребитель

57-68 Поток-потребитель записывает содержимое буферов в стандартный поток вывода. Буфер, содержащий нулевой объем данных, обозначает конец файла. Как и в потоке-производителе, критическая область, защищенная семафором mutex, пуста.

ПРИМЕЧАНИЕ

В разделе 22.3 книги [24] мы разработали пример с несколькими буферами. В этом примере производителем был обработчик сигнала SIGIO, а потребитель представлял собой основной цикл обработки (функцию dg_echo). Разделяемой переменной был счетчик nqueue. Потребитель блокировал сигнал SIGIO на время проверки или изменения счетчика.

10.12. Использование семафоров несколькими процессами

Правила совместного использования размещаемых в памяти семафоров несколькими процессами просты: сам семафор (переменная типа semt, адрес которой является первым аргументом sem_init) должен находиться в памяти, разделяемой всеми процессами, которые хотят его использовать, а второй аргумент функции sem_init должен быть равен 1.

  • Читать дальше
  • 1
  • ...
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: