Уильям Стивенс - UNIX: разработка сетевых приложений

Тут можно читать онлайн Уильям Стивенс - UNIX: разработка сетевых приложений - бесплатно ознакомительный отрывок. Жанр: comp-osnet, издательство Питер, год 2007. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    UNIX: разработка сетевых приложений
  • Автор:
  • Жанр:
  • Издательство:
    Питер
  • Год:
    2007
  • Город:
    Санкт-Петербург
  • ISBN:
    5-94723-991-4
  • Рейтинг:
    4.33/5. Голосов: 91
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Уильям Стивенс - UNIX: разработка сетевых приложений краткое содержание

UNIX: разработка сетевых приложений - описание и краткое содержание, автор Уильям Стивенс, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.

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

UNIX: разработка сетевых приложений - читать книгу онлайн бесплатно (ознакомительный отрывок), автор Уильям Стивенс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Signal(SIGCHLD, sig_chld);

в листинге 5.1, после вызова функции listen. (Необходимо сделать это до вызова функции forkдля первого дочернего процесса, причем только один раз.) Затем мы определяем обработчик сигнала — функцию sig_chld, представленную в листинге 5.6.

Листинг 5.6. Версия обработчика сигнала SIGCHLD, вызывающая функцию wait (усовершенствованная версия находится в листинге 5.8)

//tcpcliserv/sigchldwait.с

1 #include "unp.h"

2 void

3 sig_chld(int signo)

4 {

5 pid_t pid;

6 int stat;

7 pid = wait(&stat);

8 printf("child terrmnated\n", pid);

9 return;

10 }

ВНИМАНИЕ

В обработчике сигналов не рекомендуется вызов стандартных функций ввода-вывода, таких как printf, по причинам, изложенным в разделе 11.18. В данном случае мы вызываем функцию printf как средство диагностики, чтобы увидеть, когда завершается дочерний процесс.

В системах System V и Unix 98 дочерний процесс не становится зомби, если процесс задает действие SIG_IGN для SIGCHLD. К сожалению, это верно только для System V и Unix 98. В POSIX прямо сказано, что такое поведение этим стандартом не предусмотрено. Переносимый способ обработки зомби состоит в том, чтобы перехватывать сигнал SIGCHLD и вызывать функцию wait или waitpid.

Если мы откомпилируем в Solaris 9 программу, представленную в листинге 5.1, вызывая функцию Signalс нашим обработчиком sig_chld, и будем использовать функцию signalиз системной библиотеки (вместо нашей версии, показанной в листинге 5.5), то получим следующее:

solaris % tcpserv02 & запускаем сервер в фоновом режиме

[2] 16939

solaris % tcpcli01 127.0.0.1 затем клиент

hi there набираем эту строку

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

^D вводим символ конца файла

child 16942 terminated функция printf из обработчика сигнала выводит эту строку

accept error: Interrupted system call но функция main преждевременно прекращает выполнение

Последовательность шагов в этом примере такова:

1. Мы завершаем работу клиента, вводя символ EOF. TCP клиента посылает сегмент FIN серверу, и сервер отвечает сегментом ACK.

2. Получение сегмента FIN доставляет EOF ожидающей функции readlineдочернего процесса. Дочерний процесс завершается.

3. Родительский процесс блокирован в вызове функции accept, когда доставляется сигнал SIGCHLD. Функция sig_chld(наш обработчик сигнала) выполняется, функция waitполучает PID дочернего процесса и статус завершения, после чего из обработчика сигнала вызывается функция printf. Обработчик сигнала возвращает управление.

4. Поскольку сигнал был перехвачен родительским процессом, в то время как родительский процесс был блокирован в медленном (см. ниже) системном вызове (функция accept), ядро заставляет функцию acceptвозвратить ошибку EINTR(прерванный системный вызов). Родительский процесс не обрабатывает эту ошибку корректно (см. листинг 5.1), поэтому функция mainпреждевременно завершается.

Цель данного примера — показать, что при написании сетевых программ, перехватывающих сигналы, необходимо получать информацию о прерванных системных вызовах и обрабатывать их. В этом специфичном для Solaris 2.5 примере функция signalиз стандартной библиотеки С не осуществляет автоматический перезапуск прерванного вызова, то есть флаг SA_RESTART, установленный нами в листинге 5.5, не устанавливается функцией signal из системной библиотеки. Некоторые другие системы автоматически перезапускают прерванный системный вызов. Если мы запустим тот же пример в 4.4BSD, используя ее библиотечную версию функции signal, ядро перезапустит прерванный системный вызов и функция acceptне возвратит ошибки. Одна из причин, по которой мы определяем нашу собственную версию функции signalи используем ее далее, — решение этой потенциальной проблемы, возникающей в различных операционных системах (см. листинг 5.5).

Кроме того, мы всегда программируем явную функцию returnдля наших обработчиков сигналов (см. листинг 5.6), даже если функция ничего не возвращает ( void), чтобы этот оператор напоминал нам о возможности прерывания системного вызова при возврате из обработчика.

Обработка прерванных системных вызовов

Термином медленный системный вызов ( slow system call ), введенным при описании функции accept, мы будем обозначать любой системный вызов, который может быть заблокирован навсегда. Такой системный вызов может никогда не завершиться. В эту категорию попадает большинство сетевых функций. Например, нет никакой гарантии, что вызов функции acceptсервером когда-нибудь будет завершен, если нет клиентов, которые соединятся с сервером. Аналогично, вызов нашим сервером функции read(из readline) в листинге 5.2 никогда не возвратит управление, если клиент никогда не пошлет серверу строку для отражения. Другие примеры медленных системных вызовов — чтение и запись в случае программных каналов и терминальных устройств. Важным исключением является дисковый ввод-вывод, который обычно завершается возвращением управления вызвавшему процессу (в предположении, что не происходит фатальных аппаратных ошибок).

Основное применяемое здесь правило связано с тем, что когда процесс, блокированный в медленном системном вызове, перехватывает сигнал, а затем обработчик сигналов завершает работу, системный вызов может возвратить ошибку EINTR. Некоторые ядра автоматически перезапускают некоторые прерванные системные вызовы. Для обеспечения переносимости программ, перехватывающих сигналы (большинство параллельных серверов перехватывает сигналы SIGCHLD), следует учесть, что медленный системный вызов может возвратить ошибку EINTR. Проблемы переносимости связаны с написанными выше словами « могут » и « некоторые » и тем фактом, что поддержка флага POSIX SA_RESTARTне является обязательной. Даже если реализация поддерживает флаг SA_RESTART, не все прерванные системные вызовы могут автоматически перезапуститься. Например, большинство реализаций, происходящих от Беркли, никогда автоматически не перезапускают функцию select, а некоторые из этих реализаций никогда не перезапускают функции acceptи recvfrom.

Чтобы обработать прерванный вызов функции accept, мы изменяем вызов функции accept, приведенной в листинге 5.1, в начале цикла forследующим образом:

for (;;) {

clilen = sizeof(cliaddr);

if ((connfd = accept(listenfd, (SA*)&cliaddr, &clilen)) < 0) {

if (errno == EINTR)

continue; /* назад в for() */

else

err_sys("accept error");

}

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Уильям Стивенс читать все книги автора по порядку

Уильям Стивенс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




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


Отзывы читателей о книге UNIX: разработка сетевых приложений, автор: Уильям Стивенс. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x