10
Здесь многое зависит от расстановки приоритетов. Если вы хотите, чтобы всякий, читающий ваш код, тут же воскликнул: «Ну и крутой же парень написал такое!», заведомо используйте spawn()
. При желании сделать код максимально элегантным используйте fork()
, а если ставится задача хорошей читаемости и ясности кода, то очень часто достаточно и system()
.
11
Детали создания потока и и частности передачи ему параметра обстоятельно рассматриваются далее.
12
Напоминаем, что листинги, названия которых выделены подобным образом (на сером фоне), представляют собой законченные приложения. Соответствующие файлы можно найти в архивах; они могут быть воспроизведены или модифицированы для тонкого анализа результатов.
13
Тем не менее это вовсе не означает, что следует непосредственно использовать вызов spawn ()
, ведь он самый трудоемкий и чреват ошибками.
14
Часто в публикациях ссылаются на расширения реального времени POSIX 1003b (1993). Но POSIX 1003b не описывают группу pthread_*
, хотя именно в этой редакции определены семафоры sem_t
. У. Стивенс [2] указывает, что программные потоки POSIX определены в редакции 1003.1 (1995).
15
Клонирование многопоточных процессов с помощью fork()
— это отдельная песня. Хотя POSIX и предусматривает реализацию (pthread_atfork()
) такой возможности, до конца не ясно, как это работает. API QNX предоставляет эту возможность, но предупреждает, что пользователь сам отвечает за последствия. Детали механизма pthread_atfork()
см. в справочном руководстве QNX.
16
Собственно с этим и связано употребление применительно к потокам названия «легкие процессы». Впервые этот термин (LWP — lightweight process) ввела в своей технической документации для обозначения понятия, эквивалентного потоку, фирма Sun Microsystems.
17
Эта схема PID/TID описана в POSIX, но выполняется далеко не во всех UNIX-совместимых ОС. Например, вплоть до самых последних редакций ядра Linux (ситуация стала меняться только сейчас) процессы (fork()
) и потоки (pthread_create()
) (создавались на базе единого системного вызова (_clone()
) и TID являлись идентификаторами в едином ряду PID. Это может привести к трудно выявляемым ошибкам при переносе программ между двумя ОС.
18
Русскоязычную терминологию, пусть и не самую благозвучную, мы здесь заимствуем из [12].
19
В литературе неоднократно отмечалось, что ошибки многопоточных программ часто не детерминированы (могут возникать или нет в идентичных условиях исполнения), трудно воспроизводимы и могут быть крайне трудны для локализации.
20
Пользователь может изменять это поле, однако это лишено смысла и не влечет за собой никаких последствий, ведь значением текущего приоритета «управляет» ОС, например для осуществления наследования приоритетов. С другой стороны, иногда целесообразно считать значение именно этого поля, чтобы определить значение динамического приоритета потока, установленного, например, в результате того же наследования.
21
В документации неоднократно упоминается еще одна дисциплина — «адаптивная» (SCHED_ADAPTIVE
), и даже детально описывается, «как она работает». Видимо, это можно отнести только к тому, что корректировка обширной документации отстает от развития самой системы. На конференции «QNX-Россия 2003» на вопрос по поводу ADAPTIVE-диспетчеризации представители QSSL отвечали так: «Этот вид диспетчеризации был в QNX 4.xx, а в QNX 6.x вместо него введена более