Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Конспект 17 страниц.doc
Скачиваний:
14
Добавлен:
15.06.2014
Размер:
826.37 Кб
Скачать

Лекция-7:

Количество процессов, которые могут присоединиться к каналу, принципиально не ограничено. Однако если два или более процессов записывают в канал данные, то величина записи каждого из процессов ограничена определенной в системе величиной. Через некоторое время найдется процесс, считывающий данные из канала, после этого опять очередь перейдёт к данному процессу и он дозапишет информацию.

Для предотвращения такого недостатка коммуникационный канал обычно делают однонаправленным и используют его для связи между двумя процессами, причем один процесс является отправителем, а другой  получателем. Если оба процесса требуют при взаимодействии как операции передачи, так и операции приема, то целесообразно для связи между ними создать два канала.

Если дескриптора файла, связанного с записывающей стороной канала не существует, то эта сторона считается закрытой и любой процесс, пытающиеся считать данные из канала, получает оставшиеся в нем данные. Если все данные прочитаны, то получает признак конца файла. Если же не существует дескриптора файла, связанного с читающей стороной канала, а процесс пытается записать данные в канал, то ядро формирует для данного канала сигнал SIGPIPE. Действие по умолчанию на этот сигнал  завершение процесса.

В этом примере родительский процесс определяется как получатель, который читает сообщения порожденного процесса с помощью дескриптора fifo[0], причем родительский процесс сначала закрывает на запись дескриптор fifo[1]. Это требуется для того, чтобы записывающая сторона канала закрылась, когда процесс-сын после передачи данных в канал закрывает свой дескриптор fifo[1]. Процесс-сын закрывает дескриптор на чтение, а потом производит запись данных в канал, а родитель читает данные, а потом закрывает канал на чтение. Если сын не закроет канал, отец не получит признака конца файла.

Сигналы

Сигналы являются средством передачи уведомления о некотором произошедшем событии между процессами или между ядром системы и процессами. Сигналы рассматриваются как форма межпроцессорного взаимодействия, хотя по сути напоминают прерывания, генерируемые при нарушении нормального выполнения процесса. Каждый сигнал имеет уникальное имя и имеются два системных вызова для генерации сигналов.

#include <sys/types.h>

#include <signal.h>

int kill (pid_t pid, int sig);

int raise (int sig);

Системный вызов kill посылает сигнал процессу или группе процессов. Тип сигнала определяется аргументом sig, а первый аргумент определяет, кому посылается сигнал.

Если PID>0, сигнал посылается процессу, идентификатор которого равен PID.

Если PID=0, то сигнал посылается всем процессам из группы процессов, к которой принадлежит процесс, посылающий сигнал.

Если PID<1, то сигнал посылается всем процессам, идентификатор группы которых равен абсолютному значению pid.

Второй системный вызов raise предназначается для генерации сигнала sig для текущего процесса.

Системные вызовы возвращают 0 в случае успешной посылки сигнала. Kill в случае ошибки возвращает –1, а raise – ненулевое значение. В случае ошибки обнаруживаются ошибочные ситуации:

  1. EINVAL

  2. EPERM

  3. ESRCH

Первая ошибочная ситуация означает, что аргумент не является сигналом. Вторая  что процесс не правомочен посылать сигнал указанному принимающему процессу. Третья  аргумент PID не является идентификатором процесса или группы процессов. К генерации процесса могут привести следующие ситуации:

  • Ядро посылает процессу или группе процессов сигнал при нажатии пользователем определенных клавиш или их комбинаций (например, Ctrl-C).

  • Аппаратные особые ситуации (деление на 0, обращение к недопустимой области памяти, нарушение защиты памяти, отсутствие требуемой страницы в памяти и т.д.). Обычно эти ситуации определяются аппаратурой машины, и ядру операционной системы посылаются соответствующие уведомления, например, в виде прерывания, а ядро реагирует на такое событие отправкой соответствующего сигнала процессу, который находился в стадии выполнения, когда произошла особая ситуация.

  • Определенные программные состояния системы или ее компонентов. Эти причины имеют чисто программный характер. К такой ситуации относится посылка сигнала по срабатыванию таймера, установленного с помощью специального системного вызова alarm. При получении сигнала может быть выбрано одно из следующих действий реагирования:

  • игнорирование сигнала

  • перехват и самостоятельная обработка сигнала

  • выполнение действия по умолчанию

Есть два сигнала (SIGKILL и SIGSTOP), которые невозможно ни игнорировать, ни перехватывать.

Существует определенный набор сигналов. В качестве действия по умолчанию:

  • завершение текущего процесса

  • завершение и создание файла alarm

  • игнорирование.

Для определения собственных обработчиков сигналов имеются специальные системные вызовы. Самый простейший вызов сигнала:

Пример:

#include <signal.h>

void (* signal (int sig, void (* disp)(int)))(int);

static void sig_hndlr (int signv);

{

signal (SIGINT,sig_hndlr);

printf (“Получен сигнал SIGINT\n”);

//функция обработки сигнала

}

main( )

{

signal (SIGINT,sig_hndlr);

signal (SIGUSR1,SIG_DFL);

//действие по умолчанию системы

signal (SIGUSR2,SIG_IGN);

//который игнорируется

while (1);

pause ( );

}