Параллельное и распределенное программирование на С++
Шрифт:
Функции posix_spawn и posix_spawnp не обладают всей полнотой власти, которая характерна для функций fork / exec. И такой эффект вполне ожидаем. Функция fork — чрезвычайно мощная. Мы и не надеялись скопировать все ее возможности в простой и быстрой функции, не предъявляя специальных требований к оборудованию. Важно то, что функции posix_spawn и posix_spawnp очень близки к средствам создания процессов во многих операционных системах, отличных от UNIX.
Требования
К реализации функций posix_spawn и posix_spawnp предъявляются следующие требования.
• Они должны быть реализованы без использования MMU (memory management unit — блок управления памятью) или какого-то иного специального оборудования.
• Они должны быть совместимы с существующими POSIX -стандартами.
• Они должны быть эффективными.
• Их способность по замещению функции fork (в обычных условиях) должна составлять не меньше 50%.
• Система, в которой реализованы функции posix_spawn и posix_spawnp , но не реализована функция fork , должна иметь достаточную эффективность, по крайней мере для приложений реального времени.
• Система, в которой реализована функция fork и семейство функций exec, должна обладать способностью к реализации функций posix_spawn и posix_spawnp как библиотечных программ.
Двухвариантный синтаксис
POSIX-функция exec имеет несколько последовательностей вызовов с приблизительно одинаковой результативностью. Это вызвано практическими реалиями. Поскольку установившаяся практика использования функций posix_spawn существенно отличается от POSIX-варианта, мы посчитали, что простота важнее полной совместимости. Поэтому мы представили только две модификации для функции posix_spawn .
Различий в списках параметров между функциями posix_spawn и posix_spawnp практически нет; при использовании функции posix_spawnp второй параметр интерпретируется более сложно, чем при использовании функции posix_spawn .
Совместимость с POSIX.5 (Ada)
Процедуры Start_Process и Start_Process_Search из пакета привязки языка Ada POSIX_Process_Primitives к POSIX.1 . инкапсулируют действия функций fork и ехес практически так же, как это делают функции posix_spawn и posix_spawnp. Первоначально, придерживаясь цели более простого подхода, разработчики стандарта ограничили возможности функций posix_spawn и posix_spawnp подмножеством возможностей, присущих процедурам Start_Process и Start_Process_Search, отказавшись от поддержки конкретных нестандартных средств. Но на основе пожеланий группы приема стандарта усовершенствовать отображение дескрипторов файлов или совсем отказаться от них, а также по рекомендации членов рабочей группы Ada Language Bindings разработчики стандарта решили, что функции posix_spawn и posix_spawnp должны быть в достаточной степени эффективными для реализации возможностей процедур Start_Process и Start_Process_Search. Мы исходили из того, что если привязка языка Ada к такому базовому варианту уже была одобрена в качестве стандарта IEEE, то вряд ли не будут одобрены эквивалентные части С-привязки. Среди возможностей, реализованных функциями posix_spawn и posix_spawnp, можно насчитать только следующие три пункта, которые не обеспечивались процедурами Start_Process и Start_Process_Search: необязательное задание идентификационного номера группы сыновних процессов, набор сигналов, подлежащих стандартной обработке в сыновнем процессе, а также стратегия планирования (и ее параметры).
Для того чтобы привязку языка Ada в виде процедуры Start_Process можно было реализовать с помощью функции posix_spawn , функции posix_spawn пришлось бы явно передавать пустую маску сигналов и среду родительского процесса везде, где инициатор вызова процедуры Start_Process позволял установку этих аргументов по умолчанию, поскольку в функции posix_spawn такой установки аргументов по умолчанию не предусмотрено. Способность процедуры Start_Process маскировать определенные пользователем сигналы во время ее выполнения является уникальной для привязки языка Ada и должна быть обработана в самой привязке отдельно от вызова функции posix_spawn .
Группа процессов
Поле наследования группы процессов можно использовать для присоединения сыновнего процесса к су щ
Потоки
В системах, в которых отсутствует трансляция адресов, для представле н ия абстракции параллелиз м а мож н о использовать потоки, так сказать, «в обход» функций posix_spawn и posix_spawnp . Во многих случаях создания потоков для достижения параллельности вполне достаточно, но это не всегда является достойной за м еной. Использование функций posix_spawn и posix_spawnp считается более «серьезным» вариантом, чем создание потоков. Процессы имеют ряд важных атрибутов, которые отсутствуют у потоков. Даже без трансляции адресов процесс может обладать определенной защитой памяти. Каждый процесс имеет среду, включающую атрибуты защиты и характеристики файлов, а также атрибуты планирования. Процессы абстрагируют поведение множества процессоров с архитектурой неоднородной памяти лучше, чем потоки, и их удобнее использовать для отражения слабо связанных (в функциональном смысле) ветвей параллелизма.
Функции posix_spawn и posix_spawnp м огут оказаться полезны м и не для каждой конфигурации. Ведь для поддержки функционирования множества процессов недостаточно ограничиться только их созданием. В некоторых условиях общие затраты системных ресурсов на поддержку «боеспособности» нескольких процессов могут быть довольно высокими. Существующая практика показывает, что необходимость в поддержке множества процессов для систем с «малым ядром» скорее является исключением, чем правилом, а «правило» как раз образуют потоки. Поэтому для операционных систем с одним процессом рассматриваемые функции не представляют интерес.
Асинхронное уведомление об ошибках
Библиотечная реализация функций posix_spawn или posix_spawnp не позволяет выявить все возможные ошибки до создания сыновнего процесса. Стандарт IEEE Std 1003.1-2001 обеспечивает возможность индикации ошибок, возвращаемых из сыновнего процесса, которому не удалось успешно завершить операцию создания, с помощью специального статуса выхода, который можно обнаружить, используя значение статуса, возвращаемое функциями wait и waitpid .
Интерфейс stat_val и макрос, используемый для его интерпретации, не совсем подходят для цели возврата API-ошибок, но они являются единственным способом, доступным для библиотечной реализации. Таким образом, реализация может заставить сыновний процесс завершиться со статусом выхода 127 в случае любой ошибки, выявленной во вре м я порождения процесса после успешного завершения функции posix_spawn или posix_spawnp.
Разработчики стандарта для интерпретации значения stat_val предложили использовать два дополнительных макроса. Первый, WIFSPAWNFAIL, предназначен для выявления статуса, который свидетельствует о завершении сыновнего процесса по причине ошибки, обнаруженной во время выполнения операции posix_spawn или posix_spawnp , а не во время реального выполнения образа сыновнего процесса; второй макрос, WSPAWNERRNO, должен выделить значение ошибки, если макрос WIFSPAWNFAIL обнаружит сбой. К сожалению, группа приема стандарта резко возражала против этого дополнения, поскольку оно поставило бы библиотечную реализацию функции posix_spawn или posix_spawnp в зависимость от модификации функции waitpid, способной встраивать специальную информацию в значение stat_val для индикации сбоя при порождении процесса.