UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
Signal(SIGCHLD, sig_chld);
в листинге 5.1, после вызова функции
listen
fork
sig_chld
Листинг 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 terrmnatedn", 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
solaris % <b>tcpserv02 &</b> <i>запускаем сервер в фоновом режиме</i>
[2] 16939
solaris % <b>tcpcli01 127.0.0.1</b> <i>затем клиент</i>
<b>hi there </b><i>набираем эту строку</i>
hi there <i>и она отражается сервером</i>
<b>^D </b><i>вводим символ конца файла</i>
child 16942 terminated <i>функция printf из обработчика сигнала выводит эту строку</i>
accept error: Interrupted system call <i>но функция main преждевременно прекращает выполнение</i>
Последовательность шагов в этом примере такова:
1. Мы завершаем работу клиента, вводя символ EOF. TCP клиента посылает сегмент FIN серверу, и сервер отвечает сегментом ACK.
2. Получение сегмента FIN доставляет EOF ожидающей функции
readline
3. Родительский процесс блокирован в вызове функции
accept
SIGCHLD
sig_chld
wait
printf
4. Поскольку сигнал был перехвачен родительским процессом, в то время как родительский процесс был блокирован в медленном (см. ниже) системном вызове (функция
accept
accept
EINTR
main
Цель данного примера — показать, что при написании сетевых программ, перехватывающих сигналы, необходимо получать информацию о прерванных системных вызовах и обрабатывать их. В этом специфичном для Solaris 2.5 примере функция
signal
SA_RESTART
signal
accept
signal
Кроме того, мы всегда программируем явную функцию
return
void
Обработка прерванных системных вызовов
Термином медленный системный вызов (slow system call), введенным при описании функции
accept
accept
read
readline
Основное применяемое здесь правило связано с тем, что когда процесс, блокированный в медленном системном вызове, перехватывает сигнал, а затем обработчик сигналов завершает работу, системный вызов может возвратить ошибку
EINTR
SA_RESTART
SA_RESTART
select
accept
recvfrom