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

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

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

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

ПРИМЕЧАНИЕ

В разделе 26.5 мы упомянули о трех вариантах преобразования функции, которая не является безопасной в многопоточной среде, в функцию, обеспечивающую требуемую безопасность. Функция web_child вызывает функцию readline, и версия, показанная в листинге 3.12, не является безопасной в многопоточной среде. На примере, приведенном в листинге 30.20, были испробованы вторая и третья альтернативы из раздела 26.5. Увеличение быстродействия при переходе от альтернативы 3 к альтернативе 2 составило менее одного процента, вероятно, потому, что функция readline использовалась лишь для считывания значения счетчика (5 символов) от клиента. Поэтому в данной главе для простоты мы использовали более медленную версию из листинга 3.11 для сервера с предварительным порождением потоков.

30.11. Сервер TCP с предварительным порождением потоков, каждый из которых вызывает accept

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

fork
. Для систем, поддерживающих потоки, логично предположить, что имеется та же закономерность: быстрее сразу создать пул потоков при запуске сервера, чем создавать по одному потоку по мере поступления запросов от клиентов. Основная идея такого сервера заключается в том, чтобы создать пул потоков, каждый из которых вызывает затем функцию
accept
. Вместо того чтобы блокировать потоки в вызове
accept
, мы используем взаимное исключение, как в разделе 30.8. Это позволяет вызывать функцию accept только одному потоку в каждый момент времени. Использовать блокировку файла для защиты
accept
в таком случае бессмысленно, так как при наличии нескольких потоков внутри данного процесса можно использовать взаимное исключение.

В листинге 30.21 показан заголовочный файл

pthread07.h
, определяющий структуру
Thread
, содержащую определенную информацию о каждом потоке.

Листинг 30.21. Заголовочный файл pthread07.h

//server/pthread07.h

1 typedef struct {

2  pthread_t thread_tid; /* идентификатор потока */

3  long thread_count; /* количество обработанных запросов */

4 } Thread;

5 Thread *tptr; /* массив структур Thread */

6 int listenfd, nthreads;

7 socklen_t addrlen;

8 pthread_mutex_t mlock;

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

В листинге 30.22 показана функция

main
.

Листинг 30.22. Функция main для сервера TCP с предварительным порождением потоков

//server/serv07.c

 1 #include "unpthread.h"

 2 #include "pthread07.h"

 3 pthread_mutex_t mlock = PTHREAD_MUTEX_INITIALIZER;

 4 int

 5 main(int argc, char **argv)

 6 {

 7  int i;

 8  void sig_int(int), thread_make(int);

 9  if (argc == 3)

10   listenfd = Tcp_listen(NULL, argv[1], &addrlen);

11  else if (argc == 4)

12   listenfd = Tcp_1isten(argv[1], argv[2], &addrlen);

13  else

14   err_quit("usage: serv07 [ <host> ] <port#> <#threads>");

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

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

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

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

19  Signal(SIGINT, sig_int);

20  for (;;)

21   pause(); /* потоки все выполнили */

22 }

Функции

thread_make
и
thread_main
показаны в листинге 30.23.

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

//server/pthread07.c

 1 #include "unpthread.h"

 2 #include "pthread07.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  socklen_t clilen;

16  struct sockaddr *cliaddr;

17  cliaddr = Malloc(addrlen);

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

19  for (;;) {

20   clilen = addrlen;

21   Pthread_mutex_lock(&mlock);


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

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

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