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

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

Шрифт:

1 #include "unpipc.h"

2 void

3 servproc(void *cookie, char *dataptr, size_t datasize,

4 door_desc_t *descptr, size_t ndesc)

5 {

6 long arg, result;

7 sleep(6); /* клиент получает сигнал SIGCHLD */

8 arg = *((long*)dataptr);

9 result = arg * arg;

10 Door_return((char*)&result, sizeof(result), NULL, 0);

11 }

Изменим теперь клиент из листинга 15.2: установим обработчик сигнала SIGCHLD, добавив порождение процесса и завершение порожденного процесса через 2 секунды. Таким образом, через 2 секунды после вызова door_call дочерний процесс завершит работу, а родительский перехватит сигнал SIGCHLD и произойдет возврат из обработчика сигнала, прерывающий системный вызов door_call. Текст программы-клиента показан в листинге 15.22.

Листинг 15.22. Клиент, перехватывающий сигнал SIGCHLD

//doors/clientintr2.c

1 #include "unpipc.h"

2 void

3 sig_chld(int signo)

4 {

5 return; /* просто прерываем door_call */

6 }

7 int

8 main(int argc, char **argv)

9 {

10 int fd;

11 long ival, oval;

12 door_arg_t arg;

13 if (argc != 3)

14 err_quit("usage: clientintr2 <server-pathname> <integer-value>");

15 fd = Open(argv[1], O_RDWR); /* открываем дверь */

16 /* подготовка аргументов и указателя на результат */

17 ival = atol(argv[2]);

18 arg.data_ptr = (char*)&ival; /* аргументы */

19 arg.data_size = sizeof(long); /* размер аргументов */

20 arg.desc_ptr = NULL;

21 arg.desc_num = 0;

22 arg.rbuf = (char*)&oval; /* данные */

23 arg.rsize = sizeof(long); /* размер данных */

24 Signal(SIGCHLD, sig_chld);

25 if (Fork == 0) {

26 sleep(2); /* дочерний процесс */

27 exit(0); /* отправка SIGCHLD */

28 }

29 /* вызов процедуры сервера и вывод результата */

30 Door_call(fd, &arg);

31 printf(result: %ld\n", oval);

32 exit(0);

33 }

Клиенту будет возвращена та же ошибка, что и при досрочном завершении сервера — EINTR:

solaris % clientintr2 /tmp/door2 22

door_call error: interrupted system call

Поэтому нужно блокировать все сигналы, которые могут прервать вызов door_call.

Идемпотентные и неидемпотентные процедуры

А что произойдет, если мы перехватим сигнал EINTR и вызовем процедуру сервера еще раз, поскольку мы знаем, что эта ошибка возникла из-за нашего собственного прерывания системного вызова перехваченным сигналом (SIGCHLD)? Это может привести к некоторым проблемам, как мы покажем ниже.

Изменим сервер так, чтобы он выводил идентификатор вызванного потока, делал паузу в 6 секунд и выводил идентификатор потока по завершении его. В листинге 15.23 приведен текст новой процедуры сервера. 

Листинг 15.23. Процедура сервера, выводящая свой идентификатор потока дважды

//doors/serverintr3.c

1 #include "unpipc.h"

2 void

3 servproc(void *cookie, char *dataptr, size_t datasize,

4 door_desc_t *descptr, size_t ndesc)

5 {

6 long arg, result:

7 printf("thread id %ld called\n", pr_thread_id(NULL));

8 sleep(6); /* даем клиенту возможность перехватить SIGCHLD */

9 arg = *((long*)dataptr);

  • Читать дальше
  • 1
  • ...
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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