2011. Машбук (1114722), страница 38
Текст из файла (страница 38)
Эта системаиллюстрирует механизм передачи сообщений, речь о котором шла выше (см. раздел 2.4.2).Система MPI может работать на локальной машине, в многопроцессорных системах сраспределенной памятью (т.е. может работать в кластерных системах), в сети в целом (вчастности, в т.н. GRID-системах).Далее речь пойдет о конкретных средствах взаимодействия процессов (как в ОСUnix, так и в некоторых других).3.1.1 СигналыВ ОС Unix присутствует т.н.
аппарат сигналов, позволяющий одним процессамоказывать воздействия на другие процессы. Сигналы могут рассматриваться как средствоуведомления процесса о наступлении некоторого события в системе. В некотором смыслеаппарат сигналов имеет аналогию с аппаратом прерываний, поскольку последний естьтакже уведомление системы о том, что в ней произошло некоторое событие. Прерываниевызывает определенную детерминированную последовательность действий системы,135точно так же приход сигнала в процесс вызывает в нем определенную последовательностьдействий.Инициатором отправки сигнала процессу может быть как процесс, так и сама ОС.Сигналы, посылаемые ОС, уведомляют о наступлении некоторых строгопредопределенных ситуаций (как, например, завершение порожденного процесса,попытка выполнить недопустимую машинную инструкцию, попытка недопустимойзаписи в канал и т.п.), при этом каждой такой ситуации сопоставлен свой сигнал.
Дляиллюстрации приведем следующий пример. Пусть в ходе выполнения некоторогопроцесса произошло деление на ноль, вследствие чего в системе происходит прерывание,управление передается операционной системе. ОС «видит», что это прерывание «делениена ноль», и отправляет сигнал процессу, в теле которого произошла данная ошибка.Дальше процесс реагирует на получение сигнала, но об этом чуть позже.Инициатором посылки сигнала может выступать другой процесс.
В качествепримера можно привести следующую ситуацию. Пользователь ОС Unix запустилнекоторый процесс, который в некоторый момент времени зацикливается. Чтобы снятьэтот процесс со счета, пользователь может послать ему сигнал об уничтожении(например, нажав на клавиатуре комбинацию клавиш Ctrl+C, а это есть командаинтерпретатору команд послать код сигнала SIGINT). В данном случае процессинтерпретатора команд пошлет сигнал пользовательскому процессу.Аппарат сигналов является механизмом асинхронного взаимодействия, моментприхода сигнала процессу заранее неизвестен. Однако процесс может предвидетьвозможность получения того или иного сигнала и установить определенную реакцию наего приход.
В этом плане сигналы можно рассматривать как программный аналогаппаратных прерываний.Так же, как и аппарат прерываний, имеющий фиксированное количестворазличных прерываний, Unix-системы имеют фиксированный набор сигналов. Переченьсигналов, реализованных в конкретной операционной системе, обычно находится в файле<signal.h>. В этом файле перечисляется набор пар «имя сигнала — его целочисленноезначение». Ниже приведено несколько примеров (следует заметить, что в разных версияхUNIX имена сигналов могут различаться).2 - SIGINT/*прерывание*/3 - SIGQUIT /*аварийный выход*/9 - SIGKILL /*уничтожение процесса*/14 - SIGALRM /*прерывание от таймера*/18 – SIGCHLD /* процесс-потомок завершился */При получении процессом сигнала возможны три типа реакции на него (Рис.
96).Во-первых, это обработка сигнала по умолчанию. В подавляющем большинстве случаевобработка сигнала по умолчанию означает завершение процесса. В этом случаесистемным кодом завершения процесса становится номер пришедшего сигнала.Во-вторых, процесс может перехватывать обработку пришедшего сигнала. Еслипроцесс получает сигнал, то вызывается функция, принадлежащая телу процесса, котораябыла специальным образом зарегистрирована в системе как обработчик сигнала. Следуетотметить, что часть реализованных в ОС сигналов можно перехватывать, а часть сигналовперехватывать нельзя. Примером неперехватываемого сигнала может служить сигналSIGKILL (код 9), предназначенный для безусловного уничтожения процесса. Аупомянутый выше сигнал SIGINT (код 2) перехватить можно.В-третьих, сигналы можно игнорировать, т.е.
приход некоторых сигналов процессможет проигнорировать. Как и в случае с перехватываемыми сигналами, часть сигналовможно игнорировать (например, SIGINT), а часть — нет (например, SIGKILL).136Рис. 96. Реакции на получение процессом сигнала.Если в процесс одновременно доставляется несколько различных сигналов, топорядок их обработки не определен. Если же обработки ждут несколько экземпляроводного и того же сигнала, то ответ на вопрос, сколько экземпляров будет доставлено впроцесс – все или один – зависит от конкретной реализации ОС.Отдельного рассмотрения заслуживает ситуация, когда сигнал приходит в моментвыполнения системного вызова. Обработка такой ситуации в разных версиях UNIXреализована по-разному, например, обработка сигнала может быть отложена дозавершения системного вызова; либо системный вызов автоматически перезапускаетсяпосле его прерывания сигналом; либо системный вызов вернет –1, а в переменной errnoбудет установлено значение EINTR.Для отправки сигнала процессу в ОС Unix имеется системный вызов kill().#include <sys/types.h>#include <SIGNAL.H>INT KILL (PID_T PID, INT SIG);Первый параметр вызова – идентификатор процесса, которому посылается сигнал(в частности, процесс может послать сигнал самому себе).
Существует также возможностьодновременно послать сигнал нескольким процессам. Например, если значение этогопараметра есть 0, сигнал будет передан всем процессам, которые принадлежат той жегруппе, что и процесс, посылающий сигнал, за исключением процессов сидентификаторами 0 и 1.Во втором параметре передается номер посылаемого сигнала. Если этот параметрравен 0, то будет выполнена проверка корректности обращения к kill() (в частности,существование процесса с идентификатором pid), но никакой сигнал в действительностипосылаться не будет.Если процесс-отправитель не обладает правами привилегированного пользователя,то он может отправить сигнал только тем процессам, у которых реальный илиэффективный идентификатор владельца процесса совпадает с реальным или эффективнымидентификатором владельца процесса-отправителя.При успешном завершении системный вызов kill() возвращает 0, иначевозвращается -1.Чтобы установить реакцию процесса на приходящий сигнал, используетсясистемный вызов signal().#INCLUDE <SIGNAL.H>137void (*signal( int sig, void (*disp) (int))) (int);Аргумент sig определяет номер сигнала, реакцию на приход которого надоустановить.
Второй аргумент disp определяет новую реакцию на приход указанногосигнала. То есть disp — это либо определенная пользователем функция-обработчиксигнала, либо одна из констант: SIG_DFL и SIG_IGN. Первая из них указывает, чтонеобходимо установить для данного сигнала обработку по умолчанию, т.е. стандартнуюреакцию системы, а вторая — что данный сигнал необходимо игнорировать. Приуспешном завершении системный вызов возвращает указатель на предыдущийобработчик данного сигнала (он может использоваться процессом, например, длявосстановления прежней реакции на сигнал).Как видно из прототипа вызова signal(), определенная пользователем функцияобработчик сигнала должна принимать один целочисленный аргумент (в нем будетпередан номер обрабатываемого сигнала), и не возвращать никаких значений.Отметим, что механизм сигналов является достаточно ресурсоемким, ибо отправкасигнала представляет собой системный вызов, а доставка сигнала - прерываниевыполнения процесса-получателя.
Вызов функции-обработчика и возврат требуетопераций со стеком. Если мы успешно установили в качестве обработчика сигнала своюфункцию, то при возникновении сигнала выполнение процесса прерывается, фиксируетсяточка возврата и управление в процессе передается данной функции, при этом в качествефактического целочисленного параметра передается номер пришедшего сигнала (темсамым возможно использование одной функции в качестве обработчика несколькихсигналов).
Соответственно, при выходе из функции-обработчика управление передается вточку возврата и процесс продолжает свою работу.Стоит обратить внимание на то, что возможны и достаточно часто происходятситуации, когда сигнал приходит во время вызова процессом некоторого системноговызова. В этом случае последующие действия зависят от реализации системы.