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

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

Шрифт:

4 {

5 FILE *fp;

6 char *ptr;

7 ssize_t n;

8 struct mymesg mesg;

9 void sig_chld(int);

10 Signal(SIGCHLD, sig_chld);

11 for (;;) {

12 /* считывание имени файла из очереди */

13 mesg.mesg_type = 1;

14 if ((n = Mesg_recv(readid, &mesg)) == 0) {

15 err_msg("pathname missing");

16 continue;

17 }

18 mesg.mesg_data[n] = 40'; /* имя файла */

19 if ((ptr = strchr(mesg.mesg_data, ' ')) = NULL) {

20 err_msg("bogus request: %s", mesg.mesg_data);

21 continue;

22 }

23 *ptr++ = 0; /* ptr = имя файла */

24 writeid = atoi(mesg.mesg_data);

25 if (Fork == 0) { /* дочерний процесс */

26 if ((fp = fopen(ptr, "r")) == NULL) {

27 /* ошибка: нужно сообщить клиенту */

28 snprintf(mesg.mesg_data + n, sizeof(mesg.mesg_data) – n,

29 ": can't open, %s\n", strerror(errno));

30 mesg.mesg_len = strlen(ptr);

31 memmove(mesg.mesg_data, ptr, mesg.mesg_len);

32 Mesg_send(writeid, &mesg);

33 } else {

34 /* файл открыт, копируем клиенту */

35 while (Fgets(mesg.mesg_data, MAXMESGDATA, fp) != NULL) {

36 mesg.mesg_len = strlen(mesg.mesg_data);

37 Mesg_send(writeid, &mesg);

38 }

39 Fclose(fp);

40 }

41 /* отправка сообщения нулевой длины, указывающего конец файла */

42 mesg.mesg_len = 0;

43 Mesg_send(writeid, &mesg);

44 exit(0); /* завершение дочернего процесса */

45 }

46 /* родительский процесс просто зациклен */

47 }

48 }

Листинг 6.20. Функция-обертка Mesg_recv, обрабатывающая прерванный системный вызов

//svmsgmpxnq/mesg_recv.с

10 ssize_t

11 Mesg_recv(int id, struct mymesg *mptr)

12 {

13 ssize_t n;

14 do {

15 n = mesg_recv(id, mptr);

16 } while (n == –1 && errno == EINTR);

17 if (n == –1)

18 err_sys("mesg_recv error");

19 return(n);

20 }

6.9. Использование select и poll с очередями сообщений

Одним из недостатков очередей сообщений System V является то, что они идентифицируются не дескрипторами, а идентификаторами. Поэтому с ними нельзя использовать функции select и poll (глава 6 [24]).

ПРИМЕЧАНИЕ

На самом деле одна из версий Unix, а именно AIX (созданная IBM), позволяет использовать select с очередями сообщений System V, а не только с дескрипторами. Но эта возможность имеется только в AIX.

Этот недостаток часто всплывает, когда возникает необходимость написать сервер, работающий одновременно с сетевыми соединениями и с IPC. Сетевые соединения с использованием интерфейса сокетов или XTI ([24]) используют дескрипторы, что позволяет вызывать select или poll. Программные каналы и FIFO также идентифицируются дескрипторами, поэтому для них тоже допустимо использование этих функций.

Одним из решений этой проблемы является следующее: сервер должен создать канал и породить процесс, который будет заблокирован при вызове msgrcv. При получении сообщения произойдет возврат из msgrcv, дочерний процесс получит это сообщение из очереди и запишет его в канал. Затем родительский процесс может использовать функцию select для канала совместно с сетевыми соединениями. Недостаток этого подхода в том, что сообщения обрабатываются трижды: при считывании дочерним процессом с помощью msgrcv, при отправке в канал и при считывании из канала родительским процессом. Для ускорения обработки порожденный процесс может создать сегмент совместно используемой с породившим процессом памяти, а канал использовать как флаг (упражнение 12.5).

  • Читать дальше
  • 1
  • ...
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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