Пример сервера, реализованного с применением потоков
Ниже приведен пример использования потоков в серверной программе. Чтобы иметь возможность провести сравнение с реализацией, в которой используются несколько процессов, был выбран вариант службы 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.
Упражнения
- Сравните многопотоковый параллельный сервер, рассматриваемый в этой главе, с реализацией сервера в предыдущей главе, в которой используется несколько однопотоковых процессов. Какой из этих двух серверов работает быстрее? Как зависит производительность сервера от числа параллельных соединений?
- Изменится ли ответ на вопрос предыдущего упражнения, если будет исключен поток монитора?
- Прочитайте литературу с описанием функции pthread_attr_init. Для чего она применяется?
- Что произойдет с сервером, если поток монитора будет подключен к клавиатуре и пользователь введет комбинацию клавиш (т.е. остановит вывод)?
- В примере кода монитора предусмотрен захват монитором мьютекса на то время, пока он форматирует и выводит статистические данные. Откорректируйте код таким образом, чтобы монитор удерживал мьютекс лишь на время, достаточное для копирования структуры stats.
- В рассматриваемом примере программы монитора для периодического вывода статистических данных служит отдельный поток. Воспользуйтесь сигнальным механизмом Linux для реализации тех же функциональных средств. В чем состоят преимущества и недостатки каждого подхода?
- Откорректируйте код монитора таким образом, чтобы он принимал команды с клавиатуры и отвечал на каждую из них.