■ Стоимость функции fork
довольно высока, так как при ее использовании требуется скопировать все содержимое памяти из родительского процесса в дочерний, продублировать все дескрипторы и т.д. Текущие реализации используют технологию, называемую fork
остается высокой.
■ Для передачи данных между родительским и дочерним процессами fork
требуется использовать средства взаимодействия процессов (IPC). Передача информации перед вызовом fork
не вызывает затруднений, так как при запуске дочерний процесс получает от родительского копию пространства данных и копии всех родительских дескрипторов. Но возвращение информации из дочернего процесса в родительский требует большей работы.
Обе проблемы могут быть разрешены путем использования
Все потоки одного процесса совместно используют его глобальные переменные, поэтому им легко обмениваться информацией, но это приводит к необходимости синхронизации.
Однако общими становятся не только глобальные переменные. Все потоки одного процесса разделяют:
■ инструкции процесса;
■ большую часть данных;
■ открытые файлы (например, дескрипторы);
■ обработчики сигналов и вообще настройки для работы с сигналами (действие сигнала);
■ текущий рабочий каталог;
■ идентификаторы пользователя и группы пользователей.
У каждого потока имеются собственные:
■ идентификатор потока;
■ набор регистров, включая счетчик команд и указатель стека;
■ стек (для локальных переменных и адресов возврата);
■ переменная errno
;
■ маска сигналов;
■ приоритет.
Как сказано в разделе 11.18, можно рассматривать обработчик сигнала как некую разновидность потока. В традиционной модели Unix у нас имеется основной поток выполнения и обработчик сигнала (другой поток). Если в основном потоке в момент возникновения сигнала происходит корректировка связного списка и обработчик сигнала также пытается изменить связный список, обычно начинается путаница. Основной поток и обработчик сигнала совместно используют одни и те же глобальные переменные, но у каждого из них имеется свой собственный стек.
В этой книге мы рассматриваем потоки POSIX, которые также называются pthread_
. Эта глава является введением в концепцию потоков, необходимым для того, чтобы в дальнейшем мы могли использовать потоки в наших сетевых приложениях. Более подробную информацию вы можете найти в [15].
26.2. Основные функции для работы с потоками: создание и завершение потоков
В этом разделе мы рассматриваем пять основных функций для работы с потоками, а в следующих двух разделах мы используем эти функции для написания потоковой модификации клиента и сервера TCP.
Функция pthread_create
Когда программа запускается с помощью функции exec
, создается один поток, называемый pthread_create
.
#include
int pthread_create(pthread_t*
void *(*
Каждый поток процесса обладает собственным pthread_t
(как правило, это unsigned int
). При успешном создании нового потока его идентификатор возвращается через указатель tid
.