|
Программирование >> Структура ядра и системные вызовы
API sighold добавляет заданный сигнал signalmm в сигнальную маску вызывающего процесса. Это то же самое, что использование API sigset с аргументом SIG HOLD: sigset {<signal num>,SIG HOLD); API sigrelse удаляет заданный сигнал signal пит из сигнальной маски вызывающего процесса; API sigignore устанавливает метод обработки заданного сигнала signalnum в значение SIG DFL; API sigpause удаляет заданный сигнал signal num из сигнальной маски вызывающего процесса и приостанавливает процесс до тех пор, пока он не будет возобновлен сигналом signal пит. 9.4. Функция sigaction Интерфейс прикладного программирования sigaction заменяет API signal в последних версиях ОС UNIX и POSIX. 1. Подобно API signal, он вызывается процессом для задания метода обработки каждого сигнала, с которым собирается работать. Оба интерфейса прикладного программирования возвращают указатель на предьщущий метод обработки данного сигнала. Кроме того, API sigaction позволяет определить дополнительные сигналы, которые также будут блокироваться при обработке сигнала signalnum Прототип API sigaction выглядит таким образом: #include <signal.h> int sigaction ( int signal num, struct sigaction* action, struct sigaction* old action); Тип данных struct sigaction определяется в заголовке <signal.h>: struct sigaction f void (*sa handler) (int) ; sigset t sa mas)c; int sa flag; Поле sajtandler соответствует второму аргументу функции signal. В него может быть занесено значение SIGIGN, SIG DFL или определенная пользователем функция-обработчик сигнала. Поле samask наряду с сигналами, указанными в данный момент в сигнальной маске процесса, и сигналом signaljtum задает дополнительные сигналы, которые процесс будет блокировать при обработке сигнала signal пит. Аргумент signaljtum показывает, какое действие по обработке сигнала определено в аргументе action. Предьщущий метод обработки сигнала для signaljtum будет возвращен посредством аргумента old action, если это не NULL-указатель. Если аргумент action является NULL-указателем, то метод обработки сигнала вызывающего процесса для sifftaljtum останется прежним. В приведенной ниже программе 5gflc on. С показан пример использования функции sigaction: ♦include <iostream.h> ♦include <stdio.h> ♦include <unistd.h> ♦include <signal.h> void callmeO { cout catch signal endl; int mainO ( sigset t sigmaslc; struct sigaction action, old action; sigemptyset (&sigmaslc) ; if (sigaddset( &sigmaslc, SIGTERM) ==-1 II sigprocmas)c (SIG SETMASK, &sigmas)c, 0)==-l) perror( set signal mas)? ); sigemptyset (&action . sa mas)c) ; sigaddset (Saction. sa maslc, SIGSEGV) ; ♦ifdef SOLARIS 25 action.sa handler => (void (*)(int))callme; ♦else action. sa handler = callme; ♦endif action. sa f lags *= 0; if (sigaction(SIGILL,&action,&old action)==-1) perror( sigaction ); pause 0; /* ожидать прерывания сигналом */ return 0; В этом примере сигнальная маска процесса содержит сигнал SIGTERM. Затем процессом определяется обработчик для сигнала SIGINT. Указывается, что сигнал SIGSEGV должен быть блокирован при обработке процессом сигнала SIGINT. Затем процесс приостанавливает свое выполнение с помощью API pause. int sighold ( int signal num ); int sigrelse ( int signal num ); int sigignore ( int signal num ); int sigpause ( int signal num ); Пробное выполнение профаммы дает такой результат: % СС sigaction.с -о sigaction % sigaction [1] 495 % kill -INT 495 catch signal [1] Interrupt sigaction Если в процессе генерируется сигнал SIGINT, то ядро сначала устанавливает сигнальную маску процесса на блокирование сигналов SIGTERM, SIGINT и SIGSEGV. Потом оно настраивает процесс на выполнение функции-обработчика сигнала callme. Когда функция callme возвращает результат, сигнальная маска процесса восстанавливается и содержит только сигнал SIGTERM, а процесс продолжает перехватывать сигнал SIGILL. Поле sa Jlag в структуре struct sigaction используется для задания специальных методов обработки определенных сигналов. В стандарте POSIX.l установлено только два значения этого поля: О или SA NOCHLDSTOP. Флаг NOCHLDSTOP - это целое число, определенное в заголовке <signal.h>. Данный флаг может использоваться, когда аргумент signai num имеет значение SIGCHLD. Действие флага SA NOCHLDSTOP заключается в том, что ядро посылает сигнал SIGCHLD в процесс тогда, когда порожденный им процесс заверщен, а не тогда, когда он остановлен. С другой стороны, если значение sa Jlagb вызове sigaction равно О, то ядро посылает сигнал SIGCHLD в вызывающий процесс вне зависимости от того, заверщен порожденный процесс или остановлен. В ОС UNIX System V.4 определены дополнительные флаги для поля saструктуры struct sigaction. Эти флаги могут использоваться для указания метода обработки сигнала в стиле UNIX System V.3. Значение sa ag Влияние на обработку аргумента signal num SA RESETHAND Если signal num перехвачен, то sa handler устанавливается в SIGDFL до того, как вызывается функция обработчика сигнала, и signalnum не добавляется в сигнальную маску . процесса при выполнении функции-обработчика сигнала SA RESTART Если сигнал перехвачен, когда процесс выполняет системный вызов, ядро перезапускает данный вызов после возврата из функции-обработчика сигнала. Если этот флаг в sa Jlag не установлен, то после возврата из обработчика сигнала системный вызов прерывается, возвращается значение -1 и переменной егто присваивается значение EINTR 9.5. Сигнал SIGCHLD й API waitpid Когда порожденный процесс заверщается или останавливается, ядро посылает сигнал SIGCHLD в его родительский процесс. В зависимости от того, какой способ обработки сигнала SIGCHLD выбирает родительский процесс, могут происходить различные события: 1. Родительский процесс выполняет для сигнала SIGCHLD действие по умолчанию: в отличие от больщинства сигналов SIGCHLD не завершает родительский процесс. Он воздействует на родительский процесс только в том случае, если поступает в то же время, когда данный процесс приостанавливается системным вызовом waitpid. Если это произошло, то родительский процесс пробуждается , API возвращает ему код завершения и идентификатор порожденного процесса, а ядро освобождает позицию в таблице процессов, вьщеленную для порожденного процесса. Таким образом, при такой настройке родительский процесс может многократно вызывать API waitpid чтобы дождаться завершения каждого создаваемого им порожденного процесса. 2. Родительский процесс игнорирует сигнал SIGCHLD: последний отбрасывается и родительский процесс не будет затронут, даже если он выполняет системный вызов waitpid. Эффект такой настройки заключается в том, что если родительский процесс вызывает waitpid, то этот API будет приостанавливать родительский процесс до тех пор, пока не завершатся все порожденные им процессы. Затем ядро освобождает позиции в таблице порожденных процессов и API возвращает значение -1 в родительский процесс. 3. Процесс перехватывает сигнал SIGCHLD: функция-обработчик сигнала вызывается в родительском процессе при заверщении порожденного процесса. Если сигнал SIGCHLD поступает, когда родительский процесс выполняет системный вызов waitpid, то после возвращения из функции-обработчика сигнала этот API может быть перезапущен для определения статуса заверщения порожденного процесса и освобождения в таблице процессов соответствующей ему позиции. С другой стороны, в зависимости от того, какой метод обработки для сигнала SIGCHLD выбран в родительском процессе, API может быть прерван, а позиция порожденного процесса в таблице процессов освобождена не будет. Взаимодействие между SIGCHLD и API wait осуществляется так же, как между SIGCHLD и API waitpid. Более того, в ранних версиях ОС UNIX вместо SIGCHLD используется сигнал SIGCLD. Сигнал SIGCLD уже устарел, но в большинстве из последних UNIX-систем в целях обратной совместимости SIGCLD определен как идентичный сигналу SIGCHLD. 9.6. API sigsetjmp и siglongjmp f API sigsetjmp и siglong/mp имеют то же назначение, что и API setjmp, а также longjmp. И setjmp, и sigsetjmp отмечают одну или несколько позиций в пользовательской программе. Эта программа затем может вызывать API longjmp или siglongjmp для перехода в одну из отмеченных позиций. Таким образом, данные интерфейсы обеспечивают возможность передавать управ ление от одной функции к другой. Интерфейсы прикладного программирования sigsetjmp и siglong/mp определены в POSIX. 1 и большинстве UNIX-систем, которые поддерживают сигнальные маски. Прототипы функций этих API выглядят следующим образом: #include <setjmp.h> int sigsetjmp (sigjmpbuf env, int save sigmask); int siglongjmp (sigjmpbuf env, int ret val); API sigsetjmp и siglongjmp созданы для обработки сигнальных масок. Решение вопроса о том, будет ли сигнальная маска сохранена и восстановлена при вызове соответственно API setjmp и longjmp, зависит о реализации операционной системы. API sigsetjmp работает почти так же, как API setjmp, за исключением того, что он имеет второй аргумент, save sigmask, позволяющий пользователю указывать, должна ли сигнальная маска вызывающего процесса быть сохранена в переменной env. Так, если аргумент save sigmask не равен О, то сигнальная маска вызывающего процесса сохраняется; в противном случае она не сохраняется. API siglongjmp выполняет все те же операции, что и API longjmp, но, кроме того, восстанавливает сигнальную маску вызывающего процесса, если та была сохранена в переменной env. Аргумент ret val задает возвращаемое значение API sigsetjmp, когда он вызывается функцией siglongjmp. Его значение должно быть ненулевым числом; если же это значение равно О, то API siglongjmp сбрасывает его в 1. API siglongjmp обычно вызывается из определенных пользователем функций обработки сигналов. Сигнальная маска процесса модифицируется при вызове обработчика сигнала и API siglongjmp должен быть вызван (если пользователь не желает возобновить вьшолнение с того места, где программа была прервана сигналом) для того, чтобы обеспечить надлежащее восстановление сигнальной маски процесса при прыжке из функции обработки сигнала. В представленной ниже программе sigsetjmp. С показано, как можно использовать API sigsetjmp и siglonmp. Эта программа является модифицированным вариантом программы sigaction. С, описанной в разделе 9.4. Программа останавливает свою сигнальную маску так, чтобы она пропускала сигнал ilGTERM, а затем настраивает ловушку для этого сигнала. Далее программа вызывает sigsetjmp для сохранения в глобальной переменной env позиции, в которой было прервано вьшолнение программы. Заметьте, что sigsetjmp возврашает нулевое значение, когда он вызван непосредственно в пользовательской программе, а не с применением sigglongjmp. Программа приостанавливает свое выполнение с помощью API pause. Когда пользователь прерывает процесс посредстюм клавиатуры, то вызывается функция callme. Функция callme вызывает API siglongjmp для передачи управления программой обратно в функцию sigsetjmp (ее вызов выполняется в функции main), которая теперь возвращает значение, равное 2. ♦include <iostream.h> ♦include <stdio.h> ♦include <unistd.h> ♦include <signal.h> ♦include <setjmp.h> sigjmp buf env; void callme ( int sig numf ( ; ;b cout catch Signal: sigjnum endl; siglongjmp( env, 2 ); int main() ( sigset t sigmask; struct sigaction action, old action; sigemptyset(Ssigmask); if (sigaddset ( Ssigmask, SIGTERM)==-1 sigprocmask(SIG SETMASK, Ssigmask,0)==-!) perror( set signal mask ); sigemptyset(saction.sa mask) ; sigaddset(Saction.sa mask,SIGSEGV); ♦ifdef SOLARIS 25 action.sa handler = (void(*)(int))callme; ♦else action.sa handler = (void(*)())callme; ♦endif action.sa flags = 0; if (sigaction (SIGINT,saction,Sold action)==-l) perror( sigaction ); if (sigsetjmp( env, 1 ) != 0 ) ( cerr Return from signal interruptionXn ; return 0; else cerr Return from first time sigsetjmp is called\n ;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |