UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
} Pthread_mutex_unlock(&ndone_mutex);}Это означает, что главный поток никогда не переходит в спящее состояние, а просто входит в цикл, проверяя каждый раз значение переменной
ndoneНам нужен метод, с помощью которого главный цикл мог бы входить в состояние ожидания, пока один из потоков не оповестит его о том, что какая-либо задача выполнена. Эта возможность обеспечивается использованием условной переменной (conditional variable) вместе со взаимным исключением. Взаимное исключение используется для реализации блокирования, а условная переменная обеспечивает сигнальный механизм.
В терминах Pthreads условная переменная — это переменная типа
pthread_cond_t#include <pthread.h>int pthread_cond_wait(pthread_cond_t *<i>cptr</i>, pthread_mutex_t *<i>mptr</i>);int pthread_cond_signal(pthread_cond_t *<i>cptr</i>);<i>Обе функции возвращают: 0 в случае успешного выполнения, положительное значение Exxx в случае ошибки</i>Слово
signalSIGxxxПроще всего объяснить действие этих функций на примере. Вернемся к нашему примеру веб-клиента. Счетчик
ndoneint ndone;pthread_mutex_t ndone_mutex = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t ndone_cond = PTHREAD_COND_INITIALIZER;Поток оповещает главный цикл о своем завершении, увеличивая значение счетчика, пока взаимное исключение принадлежит данному потоку (блокировано им), и используя условную переменную для сигнализации.
Pthread_mutex_lock(&ndone_mutex);ndone++;Pthread_cond_signal(&ndone_cond);Pthread_mutex_unlock(&ndone_mutex);Затем основной цикл блокируется в вызове функции
pthread_cond_waitwhile (nlefttoread > 0) { while (nconn < maxnconn && nlefttoconn > 0) { /* находим файл для чтения */ ... } /* Ждем завершения выполнения какого-либо потока */ Pthread_mutex_lock(&ndone_mutex); while (ndone == 0) Pthread_cond_wait(&ndone_cond, &ndone_mutex); for (i = 0; i < nfiles; i++) { if (file[i].f_flags & F_DONE) { Pthread_join(file[i].f_tid, (void**)&fptr); /* обновляем file[i] для завершенного потока */ ... } } Pthread_mutex_unlock(&ndone_mutex);}Обратите внимание на то, что переменная
ndonepthread_cond_waitpthread_cond_waitПочему взаимное исключение всегда связано с условной переменной? «Условие» обычно представляет собой значение некоторой переменной, используемой совместно несколькими потоками. Взаимное исключение требуется для того, чтобы различные потоки могли задавать и проверять значение условной переменной. Например, если в примере кода, приведенном ранее, отсутствовало бы взаимное исключение, то проверка в главном цикле выглядела бы следующим образом:
/* Ждем завершения выполнения одного или нескольких потоков */while (ndone == 0) Pthread_cond_wait(&ndone_cond, &ndone_mutex);Но при этом существует вероятность, что последний поток увеличивает значение переменной
ndonendone == 0pthread_cond_waitПо этой же причине при вызове функции
pthread_cond_wait/* Ждем завершения выполнения одного или нескольких потоков */Pthread_mutex_lock(&ndone_mutex);while (ndone == 0) { Pthread_mutex_unlock(&ndone_mutex); Pthread_cond_wait(&ndone_cond, &ndone_mutex); Pthread_mutex_lock(&ndone_mutex);}Существует вероятность того, что по завершении выполнения поток увеличит на единицу значение переменной
ndonepthread_mutex_unlockpthread_cond_waitОбычно функция
pthread_cond_signalpthread_cond_broadcast
