События.
Операционные системы
Если значение pid равно -1, то сигнал посылается всем процессам, у которых реальный код идентификации пользователя совпадает с тем, под которым исполняется процесс, вызвавший функцию killO Если процесс, пославший сигнал, исполняется под кодом идентификации суперпользователя, то сигнал рассылается всем процессам, кроме процессов с идентификаторами 0 и 1; Механизм сигналов представляет собой… Читать ещё >
События. Операционные системы (реферат, курсовая, диплом, контрольная)
Для указания на то, что в системе произошли определенные события, существуют специальные переменные. Для объявления события служит функция post (name of event), для ожидания события — wait (name_of_ event). Для очистки этих переменных используется функция (присваивания нулевого значения) — оператор clear (name of event).
Для функционирования модели событий применяется алгоритм последовательной верхней релаксации (SOR)1 с использованием массива событий, пример применения которого показан на следующем отрезке кода:
float А[ L1U L2 ];
struct event s[ L1 ][ L2 ];
for (i = 0; i < L1; i++)
for (j = 0;j < L2;j++) { clear (s[ij[j ])};
for (j = 0;j < L2-J++) { post (s[ 0][j ])};
for (i = 0;i < L1;i+ +) {post (s[ i ][ 0 ]) };…
parfor (i = 1; i < LI-1; t++) parfor (j = 1;j < L2−1;j++)
<
wait (s[ i-1 ][j]); wait (s[ i ][j-1 ]);
Aim = (A[i-1JUI + A[i+1][j] + AliJU-11 + A[i]U+1])/4; post (sf i ][j ]);
}
Здесь операторы parfor означают циклы, которые можно выполнять параллельно.
Сигналы
Сигналы предназначены для информирования процессов о возникновении асинхронных событий. Для создания сигналов между процессами или ядром и процессами используется функция kill. В настоящее время POSIX определяет 28 сигналов, которые обычно классифицируют следующим образом[1][2]:
- • сигналы, посылаемые в случае завершения выполнения процесса, т. е. тогда, когда процесс выполняет функцию exit () или функцию signal() с параметром death of child (гибель потомка);
- • сигналы, посылаемые в случае возникновения особых ситуаций вызываемых процессом, таких как обращение к адресу, находящемуся за пределами виртуального адресного пространства процесса, или попытка записи в область памяти, открытую только для чтения (например, текст программы), или попытка исполнения привилегированной команды, а также различные аппаратные ошибки;
- • сигналы, посылаемые при возникновении неисправимых ошибок во время выполнения системных функций, таких как исчерпание системных ресурсов во время выполнения функции ехес () после освобождения исходного адресного пространства;
- • сигналы, причиной которых служит возникновение во время выполнения системной функции совершенно неожиданных ошибок, таких как обращение к несуществующей системной функции (процесс передал номер системной функции, который не соответствует ни одной из имеющихся функций), запись в канал, не связанный ни с одним из процессов чтения, а также использование недопустимого значения в параметре SEEK CUR системной функции lseek (). Казалось бы, более логично в таких случаях вместо посылки сигнала возвращать код ошибки, однако с практической точки зрения для аварийного завершения процессов, в которых возникают подобные ошибки, более предпочтительным является именно использование сигналов;
- • сигналы, посылаемые процессу, который выполняется в режиме задачи, например, сигнал тревоги (alarm), посылаемый по истечении определенного периода времени, или произвольные сигналы, которыми обмениваются процессы, использующие функцию kill();
- • сигналы, связанные с терминальным взаимодействием, например, с «зависанием» терминала (когда сигнал-носитель на терминальной линии прекращается по любой причине) или с нажатием клавиш «break» и «delete» на клавиатуре терминала;
- • сигналы, с помощью которых производится трассировка выполнения процесса.
Процесс может запоминать сигналы различных типов, но не имеет возможности запоминать количество получаемых сигналов каждого типа. Например, если процесс получает сигнал о «зависании» или об удалении процесса из системы, то он устанавливает в единицу соответствующие разряды в иоле сигналов таблицы процессов, но не может сказать, сколько экземпляров сигнала каждого типа он получил.
Ядро обрабатывает сигналы в контексте того процесса, который получает их, поэтому чтобы обработать сигналы, нужно запустить процесс. Существует три способа обработки сигналов: процесс завершается после получения сигнала, не обращает внимания на сигнал или выполняет особую (пользовательскую) функцию после его получения. Реакцией по умолчанию со стороны процесса, исполняемого в режиме ядра, является вызов функции exit{)> однако с помощью функции signalO процесс может указать другие специальные действия, принимаемые по получении тех или иных сигналов. В UNIX-подобных ОС набор возможных сигналов определен в файле sys/signal.h
Для работы с асинхронными сигналами доступны две функции — одна позволяет программе посылать сигнал самой себе (это называется «поднятием» сигнала):
#include
int raise (int sig);
Посылает сигнал sig, который прерывает нормальное исполнение программы и позволяет обработчику сигнала (если он был определен) взять управление на себя.
Вторая системная функции signalO:
Inti = * signal (int signum, void (*func)(int));
где signum — номер сигнала, при получении которого будет выполнено действие, связанное с запуском пользовательской функции;/мне — адрес функции; Inti — возвращаемое функцией значение. Вместо адреса функции процесс может передавать вызываемой процедуре signal число, равное 1 и 0. Если fune = 1, то процесс будет игнорировать все последующие поступления сигнала с номером signum, если fune = 0 (значение, но умолчанию), то процесс после получения сигнала в режиме ядра завершается.
Для посылки сигналов процессы используют системную функцию killO Синтаксис вызова функции:
#include
#include
int kill (pid_t pid, int signalnum);
где в pid указывается адресат посылаемого сигнала (область действия сигнала), а в signum — номер посылаемого сигнала. Связь между значением pid и совокупностью выполняющихся процессов следующая:
- • если pid — положительное целое число, то ядро посылает сигнал процессу с идентификатором pid;
- • если значение pid равно нулю, то сигнал посылается всем процессам, входящим в одну группу с процессом, вызвавшим функцию ?///();
- • если значение pid равно -1, то сигнал посылается всем процессам, у которых реальный код идентификации пользователя совпадает с тем, под которым исполняется процесс, вызвавший функцию killO Если процесс, пославший сигнал, исполняется под кодом идентификации суперпользователя, то сигнал рассылается всем процессам, кроме процессов с идентификаторами 0 и 1;
- • если pid — отрицательное целое число, но не -1, то сигнал посылается всем процессам, входящим в группу с номером, равным абсолютному значению pid.
Механизм сигналов представляет собой программное прерывание, посланное процессу, для того, чтобы сообщить о каком-либо событии, ожидаемом или нет. Источник сигнала не может знать отношение к этому получателя, особенно если последний решил игнорировать получение сигнала: источник об этом просто ничего не узнает! Сигналы могут быть посланы:
- • одним процессом другому: в этом случае используется системный вызов kill ();
- • от ядра к процессу (например, чтобы указать на фатальную ошибку, вызывающую разрушение процесса).
Параметры обработки, принятые по умолчанию при получении сигнала, можно изменить с помощью специального обработчика (handler). Handler связывается с сигналом посредством вызова signal (). Точно так же сигналы можно игнорировать, используя вызов:
signal (NOMSIGNAL, SIGIGN);
Вызов kill () позволяет послать сигнал процессу (по его PID) или группе процессов (по их PID). Например:
it include
/Обработка, связанная с сигналом прерывания SIGINT */ tint ()
{ /*вывод на экран и выход */ printfi «signal interruption п»); exit (1); }
rnainO
{устанавливается обработчик сигнала SIGINT */.
signal (SI G INT, tint) ;
/*ожидание возможного прерывания */ sleepOOO); exit (0);
;