-->

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

На нашем литературном портале можно бесплатно читать книгу UNIX: разработка сетевых приложений, Стивенс Уильям Ричард-- . Жанр: ОС и Сети. Онлайн библиотека дает возможность прочитать весь текст и даже без регистрации и СМС подтверждения на нашем литературном портале bazaknig.info.
UNIX: разработка сетевых приложений
Название: UNIX: разработка сетевых приложений
Дата добавления: 16 январь 2020
Количество просмотров: 381
Читать онлайн

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

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

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

Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала

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

 }

 Pthread_mutex_unlock(&ndone_mutex);

}

Это означает, что главный поток никогда не переходит в спящее состояние, а просто входит в цикл, проверяя каждый раз значение переменной

ndone
. Этот процесс называется опросом (polling) и рассматривается как пустая трата времени центрального процессора.

Нам нужен метод, с помощью которого главный цикл мог бы входить в состояние ожидания, пока один из потоков не оповестит его о том, что какая-либо задача выполнена. Эта возможность обеспечивается использованием условной переменной (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>

Слово

signal
в названии второй функции не имеет отношения к сигналам Unix
SIGxxx
.

Проще всего объяснить действие этих функций на примере. Вернемся к нашему примеру веб-клиента. Счетчик

ndone
теперь ассоциируется и с условной переменной, и с взаимным исключением:

int ndone;

pthread_mutex_t ndone_mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_cond_t ndone_cond = PTHREAD_COND_INITIALIZER;

Поток оповещает главный цикл о своем завершении, увеличивая значение счетчика, пока взаимное исключение принадлежит данному потоку (блокировано им), и используя условную переменную для сигнализации.

Pthread_mutex_lock(&amp;ndone_mutex);

ndone++;

Pthread_cond_signal(&amp;ndone_cond);

Pthread_mutex_unlock(&amp;ndone_mutex);

Затем основной цикл блокируется в вызове функции

pthread_cond_wait
, ожидая оповещения о завершении выполнения потока:

while (nlefttoread &gt; 0) {

 while (nconn &lt; maxnconn &amp;&amp; nlefttoconn &gt; 0) {

  /* находим файл для чтения */

  ...

 }

 /* Ждем завершения выполнения какого-либо потока */

 Pthread_mutex_lock(&amp;ndone_mutex);

 while (ndone == 0)

  Pthread_cond_wait(&amp;ndone_cond, &amp;ndone_mutex);

 for (i = 0; i &lt; nfiles; i++) {

  if (file[i].f_flags &amp; F_DONE) {

   Pthread_join(file[i].f_tid, (void**)&amp;fptr);

   /* обновляем file[i] для завершенного потока */

   ...

  }

 }

 Pthread_mutex_unlock(&amp;ndone_mutex);

}

Обратите внимание на то, что переменная

ndone
по-прежнему проверяется, только если потоку принадлежит взаимное исключение. Тогда, если не требуется выполнять какое-либо действие, вызывается функция
pthread_cond_wait
. Таким образом, вызывающий поток переходит в состояние ожидания, и разблокируется взаимное исключение, которое принадлежало этому потоку. Кроме того, когда управление возвращается потоку функцией
pthread_cond_wait
(после того как поступил сигнал от какого-либо другого потока), он снова блокирует взаимное исключение.

Почему взаимное исключение всегда связано с условной переменной? «Условие» обычно представляет собой значение некоторой переменной, используемой совместно несколькими потоками. Взаимное исключение требуется для того, чтобы различные потоки могли задавать и проверять значение условной переменной. Например, если в примере кода, приведенном ранее, отсутствовало бы взаимное исключение, то проверка в главном цикле выглядела бы следующим образом:

/* Ждем завершения выполнения одного или нескольких потоков */

while (ndone == 0)

 Pthread_cond_wait(&amp;ndone_cond, &amp;ndone_mutex);

Но при этом существует вероятность, что последний поток увеличивает значение переменной

ndone
после проверки главным потоком условия
ndone == 0
, но перед вызовом функции
pthread_cond_wait
. Если это происходит, то последний «сигнал» теряется, и основной цикл оказывается заблокированным навсегда, так как он будет ждать события, которое никогда не произойдет.

По этой же причине при вызове функции

pthread_cond_wait
поток должен блокировать соответствующее взаимное исключение, после чего эта функция разблокирует взаимное исключение и помещает вызывающий поток в состояние ожидания, выполняя эти действия как одну атомарную операцию. Если бы эта функция не разблокировала взаимное исключение и не заблокировала его снова после своего завершения, то выполнять эти операции пришлось бы потоку, как показано в следующем фрагменте кода:

/* Ждем завершения выполнения одного или нескольких потоков */

Pthread_mutex_lock(&amp;ndone_mutex);

while (ndone == 0) {

 Pthread_mutex_unlock(&amp;ndone_mutex);

 Pthread_cond_wait(&amp;ndone_cond, &amp;ndone_mutex);

 Pthread_mutex_lock(&amp;ndone_mutex);

}

Существует вероятность того, что по завершении выполнения поток увеличит на единицу значение переменной

ndone
и это произойдет между вызовом функций
pthread_mutex_unlock
и
pthread_cond_wait
.

Обычно функция

pthread_cond_signal
выводит из состояния ожидания один поток, на который указывает условная переменная. Существуют ситуации, когда некоторый поток знает, что из состояния ожидания должны быть выведены несколько потоков. В таком случае используется функция
pthread_cond_broadcast
, выводящая из состояния ожидания все потоки, которые блокированы условной переменной.

Перейти на страницу:
Комментариев (0)
название