Параллельное и распределенное программирование на С++
Шрифт:
Функция getrusage возвращает информацию об использовании ресурсов вызывающим процессом. Она также возвращает информацию о сыновнем процессе, завершения которого ожидает вызывающий процесс. Параметр who может иметь следующие значения:
RUSAGE_SELF
RUSAGE_CHILDREN
Если параметру who передано значение RUSAGE_SELF, то возвращаемая информация будет относиться к вызывающему процессу. Если же параметр who содержит значение RUSAGE_CHILDREN, то возвращаемая информация будет относиться к потомку вызывающего процесса. Если вызывающий процесс не ожидает завершения своего потомка, информация, связанная с ним, отбрасывается (не учитывается).
Таблица 3.7. Члены структуры rusage
Член структуры Описание
struct timeval ru_utime Время,потраченное пользователем
struct timeval ru_sutime Время,использованное системой
long ru_maxrss Максимальный размер, установленный для резидентной программы
long ru_maxixrss Размер разделяемой памяти
long ru_maxidrss Размер неразделяемой области данных
long ru_maxisrss Размер неразделяемой области стеков
long ru_minflt Количество запросов на страницы
long ru_maj flt Количество ошибок из-за отсутствия страниц
long ru_nswap Количество перекачек страниц
long ru_inblock Блочные операции по вводу данных
long ru_oublock Блочные операции операций по выводу данных
long ru_msgsnd Количество отправленных сообщений
long ru_msgrcv Количество полученных сообщений
long ru_nsignals Количество полученных сигналов
long ru_nvcsw Количество преднамеренных переключений контекста
long ru_nivcsw Количество принудительных переключений контекста
Асинхронные и синхронные процессы
Асинхронные процессы выполняются независимо один от другого. Это означает, что процесс А будет выполняться до конца безотносительно к процессу В. Между асинхронными процессами могут быть прямые родственные («родитель-сын») отношения, а могут и не быть. Если процесс А создает процесс В, они оба могут выполняться независимо, но в некоторый момент родитель должен получить статус завершения сыновнего процесса. Если между процессами нет прямых родственных отношений, у них может быть общий родитель.
Асинхронные процессы могут выполняться последовательно, параллельно или с перекрытием. Эти сценарии изображены на рис. 3.12. В ситуации 1 до самого конца выполняется процесс А, затем процесс В и процесс С выполняются до самого конца. Это и есть последовательное выполнение процессов. В ситуации 2 процессы выполняются одновременно. Процессы А и В - активные процессы. Во время выполнения процесса А процесс В находится в состоянии ожидания. В течение некоторого интервала времени оба процесса пребывают в ждущем режиме. Затем процесс В «просыпается», причем раньше процесса А, а через некоторое время «просыпается» и процесс А, и теперь оба процесса выполняются одновременно. Эта ситуация показывает, что асинхронные процессы могут выполняться одновременно только в течение определенных интервалов времени. В ситуации 3 выполнение процессов А и В перекрывается.
Рис. 3.12. Возможные сценарии асинхронных и синхронных процессов
Асинхронные процессы могут совместно использовать такие ресурсы, как файлы или память. Это может потребовать (или не потребовать) синхронизации или взаимодействия при разделении ресурсов. Если процессы выполняются последовательно (ситуация 1), то они не потребуют никакой синхронизации. Например, все три процесса, А, В и С, могут разделять некоторую глобальную переменную. Процесс А (перед тем как завершиться) записывает значение в эту переменную, затем процесс В во время своего выполнения считывает данные, хранимые в этой переменной и (перед тем как завершиться) записывает в нее «свое» значение. Затем во время своего выполнения процесс С считывает
Мы определяем синхронные процессы как процессы с перемежающимся выполнением, когда один процесс приостанавливает свое выполнение до тех пор, пока не з аверш ится другой - Например, процесс А, родительский, при выполнении создает процесс В, сыновний. Процесс А приостанавливает свое выполнение до тех пор, пока не завершится процесс В. После завершения процесса В его выходной код помещается в таблицу процессов. Тем самым процесс А уведомляется о завершении проц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 определяет, какие процессы попадают в это множество.