Параллельное и распределенное программирование на С++
Шрифт:
long ru_nivcsw Количество принудительных переключений контекста
Асинхронные и синхронные процессы
Асинхронные процессы выполняются независимо один от другого. Это означает, что процесс А будет выполняться до конца безотносительно к процессу В. Между асинхронными процессами могут быть прямые родственные («родитель-сын») отношения, а могут и не быть. Если процесс А создает процесс В, они оба могут выполняться независимо, но в некоторый момент родитель должен получить статус завершения сыновнего процесса. Если между процессами нет прямых родственных отношений, у них может быть общий родитель.
Асинхронные процессы могут выполняться последовательно, параллельно
Рис. 3.12. Возможные сценарии асинхронных и синхронных процессов
Асинхронные процессы могут совместно использовать такие ресурсы, как файлы или память. Это может потребовать (или не потребовать) синхронизации или взаимодействия при разделении ресурсов. Если процессы выполняются последовательно (ситуация 1), то они не потребуют никакой синхронизации. Например, все три процесса, А, В и С, могут разделять некоторую глобальную переменную. Процесс А (перед тем как завершиться) записывает значение в эту переменную, затем процесс В во время своего выполнения считывает данные, хранимые в этой переменной и (перед тем как завершиться) записывает в нее «свое» значение. Затем во время своего выполнения процесс С считывает данные из этой переменной. Но в ситуациях 2 и 3 процессы могут попытаться одновременно модифицировать эту переменную, поэтому здесь не обойтись без синхронизации доступа к ней.
Мы определяем синхронные процессы как процессы с перемежающимся выполнением, когда один процесс приостанавливает свое выполнение до тех пор, пока не з аверш ится другой - Например, процесс А, родительский, при выполнении создает процесс В, сыновний. Процесс А приостанавливает свое выполнение до тех пор, пока не завершится процесс В. После завершения процесса В его выходной код помещается в таблицу процессов. Тем самым процесс А уведомляется о завершении процecca В. Процесс А может продолжить выполнение, а затем завершиться или завершиться немедленно. В этом случае выполнение процессов А и В является синхронизированным. Сценарий синхронного выполнения процессов А и В (для сравнения с асинхронным) также показан на рис. 3.12.
Создание синхронных и асинхронных процессов с помощью функций fork , exec , system и posix_spawn
Функции fork , fork-exec и posix_spawn позволяют создавать асинхронные процессы. При использовании функции fork дублируется образ родительского процесса. После создания сыновнего процесса эта функция возвращает родителю (через параметр) идентификатор (PID) процесса-потомка и (обычным путем) число 0, означающее, что создание процесса прошло успешно. При этом родительский процесс не приостанавливается; оба процесса продолжают выполняться независимо от инструкции, следующей непосредственно за вызовом функции fork . При создании сыновнего процесса посредством fork-exec-комбинации его образ инициализируется с помощью образа нового процесса. Если функция exec выполнилась успешно (т.е. успешно прошла инициализация), она не возвращает родительскому процессу никакого значения. Функции posix_spawn создают образы сыновних процессов инициализируют их. Помимо идентификатора (PID), возвращаемого (через параметр) функцией posix_spawn родительскому процессу, обычным путем возвращается значение, служащее индикатором успешного порождения процесса. После выполнения функции posix_spawn оба процесса выполняются одновременно.
Функция system позволяет создавать синхронные процессы. При этом создается оболочка, которая выполняет системную команду или запускает выполняемый файл. В этом случае родительский процесс приостанавливается до тех пор, пока не завершится сыновний процесс и функция system не возвратит значение.Функция wait
Асинхронный процесс, вызвав функцию wait , может приостановить выполнение до тех пор, пока не завершится сыновний процесс. После завершения сыновнего процесса ожидающий родительский процесс считывает статус завершения своего потомка, чтобы не допустить создания процесса- «зомби». Функция wait получает статус завершения из таблицы процессов. Параметр status указывает на ту область, которая содержит статус завершения сыновнего процесса. Если родительский процесс имеет не один, а несколько сыновних процессов и некоторые из них уже завершились, функция wait считывает из таблицы процессов статус завершения только для одного сыновнего процесса. Если информация о статусе окажется доступной еще до вып олнения функции wait , эта функция завершится немедленно. Если родительский процесс не имеет ни одного потомка, эта функция возвратит код ошибки.
Функцию wait можно использовать также в том случае, когда вызывающий процесс должен ожидать до тех пор, пока не получит сигнал, чтобы затем выполнить определенные действия по его обработке.
Синопсис
#include <sys/wait.h>
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
Функция waitpid аналогична функции wait за исключением того, что она принимает дополнительные параметры pid и options. Параметр pid задает множество сыновних процессов, для которых считывается статус завершения. Другими словами, значение параметра pid определяет, какие процессы попадают в это множество.
pid > 0 Единственный сыновний процесс.
pid = 0 Любой сыновний процесс, групповой идентификатор которого совпадает с идентификатором вызывающего процесса.
pid < – 1 Любые сыновние процессы, групповой идентификатор которых равен абсолютному значению pid.
pid = – 1 Любые сыновние процессы.
Параметр options определяет, как должно происходить ожидание процесса, и может принимать одно из значений следующих констант, определенных в заголовке <sys/wait .h>:
WCONTINUED Сообщает статус завершения любого продолженного сыновнего процесса (заданного параметром pid), о статусе которого не было доложено с момента продолжения его выполнения.
WUNTRACED Сообщает статус завершения любого остановленного сыновнего процесса (заданного параметром pid), о статусе которого не было доложено с момента его останова.
WNOHANG Вызывающий процесс не приостанавливается, если статус завершения заданного сыновнего процесса недоступен.
Эти константы могут быть объединены с помощью логической операции ИЛИ и переданы в качестве параметра options (например, WCONTINUED | WUNTRACED).
Обе эти функции возвращают идентификатор (PID) сыновнего процесса, для которого получен статус завершения. Если значение, содержащееся в параметре status, равно числу 0, это означает, что сыновний процесс завершился при таких условиях:
• процесс вернул значение 0 из функции main ;
• процесс вызвал некоторую версию функции exit с аргументом 0;
• процесс был завершен, поскольку завершился последний поток процесса.
В табл. 3.8 перечислены макросы, которые позволяют вычислить значение статуса завершения.
Таблица З.8. Макросы, которые позволяют вычислить значение статуса завершения
WIFEXITED Приводится к ненулевому значению, если статус был возвращен нормально завершенным сыновним процессом
WEXITSTATUS Если значение WIFEXITED оказывается ненулевым, то оцениваются младшие 8 бит аргумента status, переданного завершенным сыновним процессом функции _exit или exit , либо значения, возвращенного функцией main