Mir-knigi.online
Книги онлайн читать бесплатно!
  • Главная
  • Жанры
  • ТОП книг
  • ТОП авторов
  • Контакты

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

Часть 357 из 399 Информация о книге

19  cliaddr = Malloc(addrlen);

20  nthreads = atoi(argv[argc - 1]);

21  tptr = Calloc(nthreads, sizeof(Thread));

22  iget = iput = 0;

23  /* создание всех потоков */

24  for (i = 0; i < nthreads; i++)

25   thread_make(i); /* завершается только основной поток */

26  Signal(SIGINT, sig_int);

27  for (;;) {

28   clilen = addrlen;

29   connfd = Accept(listenfd, cliaddr, &clilen);

30   Pthread_mutex_lock(&clifd_mutex);

31   clifd[iput] = connfd;

32   if (++iput == MAXNCLI)

33    iput = 0;

34   if (iput == iget)

35    err_quit("iput = iget = %d", iput);

36   Pthread_cond_signal(&clifd_cond);

37   Pthread_mutex_unlock(&clifd_mutex);

38  }

39 }

Создание пула потоков

23-25
 Функция
thread_make
создает все потоки.

Ожидание прихода клиентского соединения

27-38
 Основной поток блокируется в вызове функции
accept
, ожидая появления нового соединения. При появлении этого соединения дескриптор присоединенного сокета записывается в следующий элемент массива
clifd
после блокирования взаимного исключения. Мы также следим, чтобы индекс
iget
не совпал со значением индекса
iput
, что укажет на недостаточно большой размер массива. Условная переменная сигнализирует о прибытии нового запроса, и взаимное исключение разблокируется, позволяя одному из потоков пула обслужить прибывший запрос.

Функции

thread_make
и
thread_main
показаны в листинге 30.26. Первая из них идентична функции, приведенной в листинге 30.23.

Листинг 30.26. Функции thread_make и thread_main

//server/pthread08.c

 1 #include "unpthread.h"

 2 #include "pthread08.h"

 3 void

 4 thread_make(int i)

 5 {

 6  void *thread_main(void*);

 7  Pthread_create(&tptr[i].thread_tid, NULL, &thread_main, (void*)i);

 8  return; /* завершается основной поток */

 9 }

10 void*

11 thread_main(void *arg)

12 {

13  int connfd;

14  void web_child(int);

15  printf("thread %d starting\n", (int)arg);

16  for (;;) {

17   Pthread_mutex_lock(&clifd_mutex);

18   while (iget == iput)

19    Pthread_cond_wait(&clifd_cond, &clifd_mutex);

20   connfd = clifd[iget]; /* присоединенный сокет, который требуется

                              обслужить */

21   if (++iget == MAXNCLI)

22    iget = 0;

23   Pthread_mutex_unlock(&clifd_mutex);

24   tptr[(int)arg].thread_count++;

25   web_child(connfd); /* обработка запроса */

26   Close(connfd);

27  }

28 }

Ожидание присоединенного сокета, который требует обслуживания

17-26
 Каждый поток из пула пытается блокировать взаимное исключение, блокирующее доступ к массиву
clifd
. Если после того, как взаимное исключение заблокировано, оказывается, что индексы
iput
и
iget
равны, то вызывается функция
pthread_cond_wait
, и поток переходит в состояние ожидания, так как ему пока нечего делать. После прибытия очередного клиентского запроса основной поток вызывает функцию
pthread_cond_signal
, выводя тем самым из состояния ожидания поток, заблокировавший взаимное исключение. Когда этот поток получает соединение, он вызывает функцию
web_child
.

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

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

Если мы рассмотрим гистограмму количества клиентов, обслуживаемых каждым потоком из пула, то окажется, что распределение клиентских запросов по потокам будет таким же, как показано в последнем столбце табл. 30.2. Это означает, что если основной поток вызывает функцию

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

30.13. Резюме

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

0. Последовательный сервер (точка отсчета — управление процессом отсутствует).

1. Параллельный сервер, по одному вызову функции

fork
для каждого клиента.


Перейти к странице:
Предыдущая страница
Следующая страница
Жанры
  • Военное дело
  • Деловая литература
  • Детективы и триллеры
  • Детские
  • Детские книги
  • Документальная литература
  • Дом и дача
  • Дом и Семья
  • Жанр не определен
  • Зарубежная литература
  • Знания и навыки
  • История
  • Компьютеры и Интернет
  • Легкое чтение
  • Любовные романы
  • Научно-образовательная
  • Образование
  • Поэзия и драматургия
  • Приключения
  • Проза
  • Прочее
  • Психология и мотивация
  • Публицистика и периодические издания
  • Религия и духовность
  • Родителям
  • Серьезное чтение
  • Спорт, здоровье и красота
  • Справочная литература
  • Старинная литература
  • Техника
  • Фантастика и фентези
  • Фольклор
  • Хобби и досуг
  • Юмор
Mir-knigi.online

Бесплатная онлайн библиотека для чтения книг без регистрации с телефона или компьютера. У нас собраны последние новинки, мировые бестселлеры книжного мира.

Контакты
  • [email protected]
Информация
  • Карта сайта
© mir-knigi.online, 2026. | Вход