Читаем UNIX Network Programming. Volume 2 Second Edition. Interprocess Communications полностью

■ для передачи информации между родительским и дочерним процессами необходимо использовать одну из форм IPC после вызова fork. Передать информацию дочернему процессу легко: это можно сделать до вызова fork. Однако передать ее обратно может быть достаточно сложно.

Потоки помогают решить обе проблемы. Часто они называются «облегченными процессами» (lightweight processes), поскольку поток проще, чем процесс. Создание потока может занимать по времени меньше одной десятой создания процесса.

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

■ инструкции процесса;

■ большую часть данных;

■ открытые файлы (дескрипторы);

■ обработчики сигналов и вообще настройки для работы с сигналами;

■ текущий рабочий каталог;

■ идентификатор пользователя и группы.

Однако каждый поток имеет свои собственный:

■ идентификатор потока;

■ набор регистров, включая PC и указатель стека;

■ стек (для локальных переменных и адресов возврата);

■ errno;

■ маску сигналов;

■ приоритет.

<p>Б.2. Основные функции для работы с потоками: создание и завершение</p>

В этом разделе мы опишем пять основных функций для работы с потоками.

Функция pthread_create

При запуске пpoгрaммы вызовом exec создается единственный поток, называемый начальным потоком, или главным (initial thread). Добавочные потоки создаются вызовом pthread_create:

#include pthread.h

int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*func) (void *), void *arg);

/* Возвращает 0 в случае успешного завершения, положительное значение Еххх – в случае ошибки */

Каждый поток процесса обладает собственным идентификатором потока, который имеет тип pthread_t. При успешном создании нового потока его идентификатор возвращается через указатель tid.

Каждый поток обладает некоторым количеством атрибутов: приоритетом, начальным размером стека, признаком демона и т. п. При создании потока эти атрибуты могут быть указаны с помощью переменной типа pthread_attr_t, значение которой имеет более высокий приоритет, чем значения по умолчанию. Обычно мы используем значения по умолчанию. При этом аргумент attr является нулевым указателем.

Наконец, при создании потока мы должны указать функцию, которую он будет выполнять, — начальную функцию потока (thread start function). Поток запускается вызовом этой функции и завершается либо явно (вызовом pthread_exit), либо неявно (возвратом из этой функции). Адрес функции указывается в аргументе func, и вызывается она с единственным аргументом — указателем arg. Если функции нужно передать несколько аргументов, следует упаковать их в структуру и передать ее адрес в качестве единственного аргумента начальной функции.

Обратите внимание на объявления func и arg. Функция принимает один аргумент — указатель типа void, и возвращает один аргумент — такой же указатель. Это дает нам возможность передать потоку указатель на что угодно и получить в ответ такой же указатель.

Функции Posix для работы с потоками обычно возвращают 0 в случае успешного завершения работы и ненулевое значение в случае ошибки. В отличие от большинства системных функций, возвращающих –1 в случае ошибки и устанавливающих значение errno равным коду ошибки, функции Pthread возвращают положительный код ошибки. Например, если pthread_create не сможет создать новый поток из-за превышения системного oгрaничeния на потоки, эта функция вернет значение EAGAIN. Функции Pthread не устанавливают значение переменной errno. Несоответствий при их вызове не возникает, поскольку ни один из кодов ошибок не имеет нулевого значения (sys/errno.h).

Функция pthread_join

Мы можем ожидать завершения какого-либо процесса, вызвав pthread_join. Сравнивая потоки с процессами Unix, можно сказать, что pthread_create аналогична fork, a pthread_join — waitpid:

#include pthread.h

int pthread_join(pthread_t tid, void **status);

/* Возвращает 0 в случае успешного завершения, положительное значение Еххх – в случае ошибки */

Мы должны указать идентификатор потока, завершения которого ожидаем. К сожалению, невозможно задать режим ожидания завершения нескольких потоков (аналога waitpid с идентификатором процесса –1 нет).

Если указатель status ненулевой, возвращаемое потоком значение (указатель на объект) сохраняется в ячейке памяти, на которую указывает status.

Функция pthread_self
Перейти на страницу:

Похожие книги

Основы программирования в Linux
Основы программирования в Linux

В четвертом издании популярного руководства даны основы программирования в операционной системе Linux. Рассмотрены: использование библиотек C/C++ и стан­дартных средств разработки, организация системных вызовов, файловый ввод/вывод, взаимодействие процессов, программирование средствами командной оболочки, создание графических пользовательских интерфейсов с помощью инструментальных средств GTK+ или Qt, применение сокетов и др. Описана компиляция программ, их компоновка c библиотеками и работа с терминальным вводом/выводом. Даны приемы написания приложений в средах GNOME® и KDE®, хранения данных с использованием СУБД MySQL® и отладки программ. Книга хорошо структурирована, что делает обучение легким и быстрым. Для начинающих Linux-программистов

Нейл Мэтью , Ричард Стоунс , Татьяна Коротяева

ОС и Сети / Программирование / Книги по IT
97 этюдов для архитекторов программных систем
97 этюдов для архитекторов программных систем

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

Билл де Ора , Майкл Хайгард , Нил Форд

Программирование, программы, базы данных / Базы данных / Программирование / Книги по IT
Программист-прагматик. Путь от подмастерья к мастеру
Программист-прагматик. Путь от подмастерья к мастеру

Находясь на переднем крае программирования, книга "Программист-прагматик. Путь от подмастерья к мастеру" абстрагируется от всевозрастающей специализации и технических тонкостей разработки программ на современном уровне, чтобы исследовать суть процесса – требования к работоспособной и поддерживаемой программе, приводящей пользователей в восторг. Книга охватывает различные темы – от личной ответственности и карьерного роста до архитектурных методик, придающих программам гибкость и простоту в адаптации и повторном использовании.Прочитав эту книгу, вы научитесь:Бороться с недостатками программного обеспечения;Избегать ловушек, связанных с дублированием знания;Создавать гибкие, динамичные и адаптируемые программы;Избегать программирования в расчете на совпадение;Защищать вашу программу при помощи контрактов, утверждений и исключений;Собирать реальные требования;Осуществлять безжалостное и эффективное тестирование;Приводить в восторг ваших пользователей;Формировать команды из программистов-прагматиков и с помощью автоматизации делать ваши разработки более точными.

А. Алексашин , Дэвид Томас , Эндрю Хант

Программирование / Книги по IT