Вход/Регистрация
Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform
вернуться

Кёртен Роб

Шрифт:
Создание процесса и потоки

Предположим, что у вас есть процесс, и вы еще не создали никаких потоков (т.е., вы работаете с одним потоком — тем, который вызвал функцию main). Если вызвать функцию fork, то будет создан другой процесс, и тоже с одним потоком.

Это был простейший пример.

Теперь предположим, что в вашем процессе вы вызвали pthread_create для создания другого потока. Если вы теперь вызовете функцию fork, она возвратит ENOSYS (что означает, что функция не поддерживается)! Почему так?

Вы можете верить этому или нет, но это POSIX-совместимая ситуация. POSIX утверждает, что функция fork может возвращать ENOSYS. На самом же деле происходит вот что: Си-библиотека QNX/Neutrino не рассчитана на ветвление процесса с потоками. Когда вы вызываете pthread_create, эта функция устанавливает флаг, сигнализирующий что-то типа «не позволяйте этому процессу применять fork, потому что механизм ветвления в данном случае не определен». Затем, при вызове fork, этот флаг проверяется и, если он установлен, это принуждает fork возвратить значение ENOSYS.

Такая реализация была сделана преднамеренно, и причина этого кроется в потоках и мутексах. Если бы этого ограничения не было (и оно может быть снято в будущих версиях QNX/ Neutrino), то вновь созданный процесс, как и предполагается, имел бы то же самое число потоков, что и исходный. Однако, тут возникает сложность, потому что некоторые из исходных потоков могут являться владельцами мутексов. Поскольку вновь создаваемый процесс имеет ту же область данных, что и исходный, библиотека должна была бы отслеживать, какие мутексы принадлежат каким потокам в исходном процессе, и затем дублировать принадлежность мутексов в новом процессе. Это не является невозможным: есть функция, называемая pthread_atfork, которая обеспечивает процессу возможность обрабатывать такие ситуации. Однако, на момент написания этой книги функциональные возможности pthread_atfork используются не всеми мутексами в Си-библиотеке QNX/Neutrino.

Так что же использовать?

Очевидно, если вы переносите в QNX/Neutrino программу из другой ОС, вы пожелаете использовать те же механизмы, что и в исходной программе. Я бы посоветовал избегать в новом коде применения функции fork, и вот почему:

• функция fork не работает с несколькими потоками — см. выше;

• при работе с fork в условиях многопоточности вы должны будете зарегистрировать обработчик pthread_atfork и локировать каждый мутекс по отдельности перед собственно ветвлением, а это усложнит структуру программы;

• дочерние процессы, созданные fork, копируют все открытые дескрипторы файлов. Как мы увидим позже в главе «Администратор ресурсов», это требует много дополнительных усилий, которые может быть совершенно напрасными, если дочерний процесс затем сразу сделает exec и тем самым закроет все открытые дескрипторы.

Выбор между семействами функций vfork и spawn сводится к переносимости, а также того, что должны делать родительский и дочерний процесс. Функция vfork задержит выполнение до тех пор, пока дочерний процесс не вызовет exec или не завершится, тогда как семейство spawn может позволить работать обоим процессам одновременно. Впрочем, в разных ОС поведение функции vfork может несколько отличаться.

Запуск потока

Теперь, когда мы знаем, как запустить другой процесс, давайте рассмотрим, как осуществить запуск другого потока.

Любой поток может создать другой поток в том же самом процессе; на это не налагается никаких ограничений (за исключением объема памяти, конечно!) Наиболее общий путь реализации этого — использование вызова функций POSIX pthread_create:

#include <pthread.h>

int pthread_create(pthread_t *thread,

 const pthread_attr_t *attr,

 void*(*start_routine)(void*), void *arg);

Функция pthread_create имеет четыре аргумента :

thread указатель на
pthread_t
, где хранится идентификатор потока
attr атрибутная запись
start_routine подпрограмма, с которой начинается поток
arg параметр, который передается подпрограмме start_routine

Отметим, что указатель thread и атрибутная запись (attr) — необязательные элементы, вы может передавать вместо них NULL.

Параметр thread может использоваться для хранения идентификатора вновь создаваемого потока. Обратите внимание, что в примерах, приведенных ниже, мы передадим NULL, обозначив этим, что мы не заботимся о том, какой идентификатор будет иметь вновь создаваемый поток.

Если бы нам было до этого дело, мы бы сделали так:

  • Читать дальше
  • 1
  • ...
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: