Системное программирование в UNIX средствами Free Pascal

       

Как вскоре увидим, структура sigactionrec,


uses linux;
Procedure SigAction(Signo:Integer; Var Act,OAct:PSigActionRec);
Как вскоре увидим, структура sigactionrec, в свою очередь, также содержит набор сигналов. Первый параметр signo задает отдельный сигнал, для которого нужно определить действие. Чтобы это действие выполнялось, процедура sigaction должна быть вызвана до получения сигнала типа signo. Значением переменной signo может быть любое из ранее определенных имен сигналов, за исключений SIGSTOP и SIGKILL, которые предназначены только для остановки или завершения процесса и не могут обрабатываться по-другому.
Второй параметр, act, определяет обработчика сигнала signo. Третий параметр, oact, если не равен nil, указывает на структуру, куда будет помещено описание старого метода обработки сигнала. Рассмотрим структуру sigactionrec, определенную в файле linux:
SigActionRec  =  packed  record
  Handler    :  record
     case  byte  of
        0:  (Sh:  SignalHandler); (* Функция обработчика *)
        1:  (Sa:  TSigAction);
     end;
  Sa_Mask      :  SigSet;  (* Сигналы, которые блокируются
                              во время обработки сигнала *)
  Sa_Flags     :  Longint; /* Флаги, влияющие


                              на поведение сигнала */
  Sa_restorer  :  SignalRestorer;  {  Obsolete  -  Don't  use  }
end;
Эта структура кажется сложной, но давайте рассмотрим ее поля по отдельности. Первое поле, handler, задает обработчик сигнала signo. Это поле может иметь три вида значений:
–        SIG_DFL – константа, сообщающая, что нужно восстановить обработку сигнала по умолчанию (для большинства сигналов это завершение процесса);
–        SIG_IGN – константа, означающая, что нужно игнорировать данный сигнал (ignore the signal). He может использоваться для сигналов SIGSTOP и SIGKILL;
–        адрес функции, принимающей аргумент типа int. Если функция объявлена в тексте программы до заполнения sigaction, то полю handler.sh/handler.sa можно просто присвоить имя функции. Компилятор поймет, что имелся в виду ее адрес. Эта функция будет выполняться при получении сигнала signo, а само значение signo будет передано в качестве аргумента вызываемой функции. Управление будет передано функции, как только процесс получит сигнал, какой бы участок программы при этом не выполнялся. После возврата из функции управление будет снова передано процессу и продолжится с точки, в которой выполнение процесса было прервано. Этот механизм станет понятен из следующего примера.


Функция- обработчик может быть одного из двух типов:
type
  TSigAction = procedure(Sig: Longint; SigContext: SigContextRec);cdecl;
  SignalHandler = Procedure (Sig: Integer);cdecl;
Второе поле, sa_mask, демонстрирует первое практическое использование набора сигналов. Сигналы, заданные в поле
sa_mask, будут блокироваться во время выполнения функции, заданной полем handler. Это не означает, что эти сигналы будут игнорироваться, просто их обработка будет отложена до завершения функции. При входе в функцию перехваченный сигнал также будет неявно добавлен к текущей маске сигналов. Все это делает механизм сигналов более надежным механизмом межпроцессного взаимодействия, чем он был в ранних версиях системы UNIX.[9]
Тип поля sa_mask, sigset, ограниченно совместим с типом sigset_t. Размер типа sigset_t определяется константой
_SIGSET_NWORDS=1024 div (8 * sizeof (longint));
Это в четыре раза больше размера типа sigset, поэтому при переходе к нему необходимо использовать поле __val[0] типа sigset_t. К примеру,
sa_mask:=mask.__val[0];
Поле sa_flags может использоваться для изменения характера реакции на сигнал signo. Например, после возврата из обработчика можно вернуть обработчик по умолчанию SIG_DFL, установив значение поля sa_flags равным SA_RESETHAND. Если же значение поля sa_flags установлено равным SA_SIGINFO, то обработчику сигнала будет передаваться дополнительная информация.
Все это достаточно трудно усвоить, поэтому рассмотрим несколько примеров. В действительности все намного проще, чем кажется.

Содержание раздела