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

29   child_make(i, listenfd, addrlen); /* родительский процесс

                                          завершается */

30   FD_SET(cptr[i].child_pipefd, masterset);

31   maxfd = max(maxfd, cptr[i].child_pipefd);

32  }

33  Signal(SIGINT, sig_int);

34  for (;;) {

35   rset = masterset;

36   if (navail = 0)

37    FD_CLR(listenfd, rset); /* выключаем, если нет свободных

                                  дочерних процессов */

38   nsel = Select(maxfd + 1, rset, NULL, NULL, NULL);

39   /* проверка новых соединений */

40   if (FD_ISSET(listenfd, rset)) {

41    clilen = addrlen;

42    connfd = Accept(listenfd, cliaddr, clilen);

43    for (i = 0; i nchildren; i++)

44     if (cptr[i].child_status == 0)

45      break; /* свободный */

46    if (i == nchildren)

47     err_quit("no available children");

48    cptr[i].child_status = 1; /* отмечаем этот дочерний процесс как

                                   занятый */

49    cptr[i].child_count++;

50    navail--;

51    n = Write_fd(cptr[i].child_pipefd, 1, connfd);

52    Close(connfd);

53    if (--nsel == 0)

54     continue; /* с результатами select закончено */

55   }

56   /* поиск освободившихся дочерних процессов */

57   for (i = 0; i nchildren; i++) {

58    if (FD_ISSET(cptr[i].child_pipefd, rset)) {

59     if ((n = Read(cptr[i].child_pipefd, rc, 1)) == 0)

60      err_quit("child %d terminated unexpectedly", i);

61     cptr[i].child_status = 0;

62     navail++;

63     if (--nsel == 0)

64      break; /* с результатами select закончено */

65    }

66   }

67  }

68 }

Отключение прослушиваемого сокета в случае отсутствия свободных дочерних процессов

36-37 Счетчик navailотслеживает количество свободных дочерних процессов. Если его значение становится равным нулю, прослушиваемый сокет в наборе дескрипторов функции selectвыключается. Это предотвращает прием нового соединения в тот момент, когда нет ни одного свободного дочернего процесса. Ядро по- прежнему устанавливает эти соединения в очередь, пока их количество не превысит значения аргумента backlogфункции listen, заданного для прослушиваемого сокета, но мы не хотим их принимать, пока у нас не появится свободный дочерний процесс, готовый обрабатывать клиентский запрос.

Прием нового соединения

39-55 Если прослушиваемый сокет готов для считывания, можно принимать ( accept) новое соединение. Мы находим первый свободный дочерний процесс и передаем ему присоединенный сокет с помощью функции write_fd, приведенной в листинге 15.11. Вместе с дескриптором мы передаем 1 байт, но получатель не интересуется содержимым этого байта. Родитель закрывает присоединенный сокет.

Мы всегда начинаем поиск свободного дочернего процесса с первого элемента массива структур Child. Это означает, что новое соединение для обработки поступившего клиентского запроса всегда получает первый элемент этого массива. Этот факт мы проверим при рассмотрении табл. 30.2 и значения счетчика child_countпосле завершения работы сервера. Если мы не хотим оказывать такое предпочтение первому элементу массива, мы можем запомнить, какой дочерний процесс получил последнее клиентское соединение, и каждый раз начинать поиск свободного дочернего процесса со следующего за ним, а по достижении конца массива переходить снова к первому элементу. В этом нет особого смысла (на самом деле все равно, какой дочерний процесс обрабатывает очередное соединение, если имеется несколько свободных дочерних процессов), если только планировочный алгоритм операционной системы не накладывает санкций на процессы, которые требуют относительно больших временных затрат центрального процессора. Более равномерное распределение загрузки между всеми дочерними процессами приведет к выравниванию времен, затраченных на их выполнение.

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

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

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

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

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

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

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

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

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