Читаем UNIX: разработка сетевых приложений полностью

Функция waitpidпредоставляет более гибкие возможности выбора ожидаемого процесса и его блокирования. Прежде всего, в аргументе pidзадается идентификатор процесса, который мы будем ожидать. Значение -1 говорит о том, что нужно дождаться завершения первого дочернего процесса. (Существуют и другие значения идентификаторов процесса, но здесь они нам не понадобятся.) Аргумент optionsпозволяет задавать дополнительные параметры. Наиболее общеупотребительным является параметр WNOHANG: он сообщает ядру, что не нужно выполнять блокирование, если нет завершенных дочерних процессов.

<p>Различия между функциями wait и waitpid</p>

Теперь мы проиллюстрируем разницу между функциями waitи waitpid, используемыми для сброса завершенных дочерних процессов. Для этого мы изменим код нашего клиента TCP так, как показано в листинге 5.7. Клиент устанавливает пять соединений с сервером, а затем использует первое из них ( sockfd[0]) в вызове функции str_cli. Несколько соединений мы устанавливаем для того, чтобы породить от параллельного сервера множество дочерних процессов, как показано на рис. 5.2.

Рис. 5.2. Клиент, установивший пять соединений с одним и тем же параллельным сервером

Листинг 5.7. Клиент TCP, устанавливающий пять соединений с сервером

/ /tcpcliserv/tcpcli04.c

 1 #include "unp.h"

 2 int

 3 main(int argc, char **argv)

 4 {

 5  int i, sockfd[5];

 6  struct sockaddr_in servaddr;

 7  if (argc != 2)

 8   err_quit("usage: tcpcli ");

 9  for (i = 0; i < 5; i++) {

10   sockfd[i] = Socket(AF_INET, SOCK_STREAM, 0);

11   bzero(&servaddr, sizeof(servaddr));

12   servaddr.sin_family = AF_INET;

13   servaddr.sin_port = htons(SERV_PORT);

14   Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

15   Connect(sockfd[i], (SA*)&servaddr, sizeof(servaddr));

16  }

17  str_cli(stdin, sockfd[0]); /* эта функция выполняет все необходимые

                               действия для формирования запроса клиента */

18  exit(0);

19 }

Когда клиент завершает работу, все открытые дескрипторы автоматически закрываются ядром (мы не вызываем функцию close ,а пользуемся только функцией exit) и все пять соединений завершаются приблизительно в одно и то же время. Это вызывает отправку пяти сегментов FIN, по одному на каждое соединение, что, в свою очередь, вызывает примерно одновременное завершение всех пяти дочерних процессов. Это приводит к доставке пяти сигналов SIGCHLDпрактически в один и тот же момент, что показано на рис. 5.3.

Доставка множества экземпляров одного и того же сигнала вызывает проблему, к рассмотрению которой мы и приступим.

Рис. 5.3. Клиент завершает работу, закрывая все пять соединений и завершая все пять дочерних процессов

Сначала мы запускаем сервер в фоновом режиме, а затем — новый клиент. Наш сервер, показанный в листинге 5.1, несколько модифицирован — теперь в нем вызывается функция signalдля установки обработчика сигнала SIGCHLD, приведенного в листинге 5.6.

linux % tcpserv03 &

[1] 20419

linux % tcpcli04 206.62.226.35

hello мы набираем эту строку

hello и она отражается сервером

^D    мы набираем символ конца файла

child 20426 terminated выводится сервером

Первое, что мы можем заметить, — данные выводит только одна функция printf, хотя мы предполагаем, что все пять дочерних процессов должны завершиться. Если мы выполним программу ps, то увидим, что другие четыре дочерних процесса все еще существуют как зомби.

PID TTY TIME CMD

20419 pts/6 00:00:00 tcpserv03

20421 pts/6 00:00:00 tcpserv03

20422 pts/6 00:00:00 tcpserv03

20423 pts/6 00:00:00 tcpserv03

Перейти на страницу:

Похожие книги

Основы программирования в Linux
Основы программирования в Linux

В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стан­дартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым. Для начинающих Linux-программистов

Нейл Мэтью , Ричард Стоунс , Татьяна Коротяева

ОС и Сети / Программирование / Книги по IT
1001 совет по обустройству компьютера
1001 совет по обустройству компьютера

В книге собраны и обобщены советы по решению различных проблем, которые рано или поздно возникают при эксплуатации как экономичных нетбуков, так и современных настольных моделей. Все приведенные рецепты опробованы на практике и разбиты по темам: аппаратные средства персональных компьютеров, компьютерные сети и подключение к Интернету, установка, настройка и ремонт ОС Windows, работа в Интернете, защита от вирусов. Рассмотрены не только готовые решения внезапно возникающих проблем, но и ответы на многие вопросы, которые возникают еще до покупки компьютера. Приведен необходимый минимум технических сведений, позволяющий принять осознанное решение.Компакт-диск прилагается только к печатному изданию книги.

Юрий Всеволодович Ревич

Программирование, программы, базы данных / Интернет / Компьютерное «железо» / ОС и Сети / Программное обеспечение / Книги по IT