Пример сервера, реализованного с применением потоков

Опубликовано в Технологии > Серверные технологии

Ниже приведен пример использования потоков в серверной программе. Чтобы иметь возможность провести сравнение с реализацией, в которой используются несколько процессов, был выбран вариант службы ECHO, описанный в предыдущей главе. Многопотоковый сервер, рассматриваемый в качестве примера в настоящей главе, действует по такому же алгоритму параллельной работы с установлением логического соединения; единственное различие заключается в реализации. После инициализации ведущий поток, выполняющий основную программу, входит в бесконечный цикл, в котором он снова и снова блокируется в вызове функции accept, ожидая поступления запроса на установление соединения TCP. После получения входящего запроса в ведущем потоке вызывается функция pthread_create для создания нового потока, предназначенного для обслуживания соединения. Ведущий поток продолжает работать в цикле и ожидает поступления очередного запроса на установление соединения. Во вновь созданном потоке выполняется процедура TCPechod, в основе которой лежит цикл, выполняющий прием данных из соединения TCP и передачу тех же данных назад отправителю. Код сервера содержится в файле TCPmtechod.c.

/* TCPmtechod.c - главная процедура TCPechod, prstats */  

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

12.9. Текущий контроль и управление

В этом примере с серверной программой рассматривается механизм текущего контроля, отсутствовавший в предыдущих примерах, — монитор. Хотя здесь речь идет о простом мониторе, наглядно показано, как может использоваться монитором разделяемая память для взаимодействия с ведомыми потоками. Монитор реализован как отдельный поток, выполняющий процедуру prstats. В рассматриваемом примере кода в основе процедуры prstats лежит бесконечный цикл. При каждом проходе по циклу монитор выводит статистические данные о состоянии соединений, а затем переходит в состояние ожидания на число секунд, заданное константой INTERVAL. Вывод содержит данные о числе действующих соединений, завершенных соединений, общей продолжительности соединений и о среднем числе байтов, передаваемых через каждое соединение.

Для взаимодействия потока монитора и ведомых потоков используется разделяемая глобальная структура данных. Каждый ведомый поток вносит в структуру stats информацию о своем соединении, а монитор извлекает эту информацию через каждые INTERVAL секунд. Для обеспечения того, чтобы только один поток одновременно мог получить доступ к разделяемой структуре, в сервере используется мьютекс stats. stjnutex. Поток ожидает освобождения мьютекса, прежде чем обратиться к структуре, и освобождает его после использования этой структуры. Не знаешь? Автошколы Москвы ЮЗАО проводят набор и на сайте можно записаться!

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

12.10. Резюме

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

Материал для дальнейшего изучения

Функции потоков описаны в оперативном руководстве, которое входит в поставку операционной системы Linux.

Упражнения

  1. Сравните многопотоковый параллельный сервер, рассматриваемый в этой главе, с реализацией сервера в предыдущей главе, в которой используется несколько однопотоковых процессов. Какой из этих двух серверов работает быстрее? Как зависит производительность сервера от числа параллельных соединений?
  2. Изменится ли ответ на вопрос предыдущего упражнения, если будет исключен поток монитора?
  3. Прочитайте литературу с описанием функции pthread_attr_init. Для чего она применяется?
  4. Что произойдет с сервером, если поток монитора будет подключен к клавиатуре и пользователь введет комбинацию клавиш (т.е. остановит вывод)?
  5. В примере кода монитора предусмотрен захват монитором мьютекса на то время, пока он форматирует и выводит статистические данные. Откорректируйте код таким образом, чтобы монитор удерживал мьютекс лишь на время, достаточное для копирования структуры stats.
  6. В рассматриваемом примере программы монитора для периодического вывода статистических данных служит отдельный поток. Воспользуйтесь сигнальным механизмом Linux для реализации тех же функциональных средств. В чем состоят преимущества и недостатки каждого подхода?
  7. Откорректируйте код монитора таким образом, чтобы он принимал команды с клавиатуры и отвечал на каждую из них.