подписка
Эта статья в значительной степени или полностью опирается на один источник . ( февраль 2010 г. ) |
![]() | Тема этой статьи Википедии может не соответствовать общему правилу по известности . ( август 2020 г. ) |
В вычислениях, sigaction
— это API-интерфейс функции, определенный POSIX , чтобы предоставить программисту доступ к тому, каким должно быть поведение программы при получении определенных сигналов ОС .
Общий
[ редактировать ]В Unix-подобных операционных системах одним из средств межпроцессного взаимодействия являются сигналы. Когда исполняющая единица ( процесс или поток ) получает сигнал от ОС, она должна отреагировать каким-то образом, определенным таблицей данных и общепринятым значением этого сигнала (т. е. путем сброса своих данных, остановки выполнения, синхронизации чего-либо...).
The sigaction()
системный вызов используется для объявления поведения программы, если она получит один конкретный сигнал, не зарезервированный системой. Это делается путем предоставления вместе с системным вызовом структуры, содержащей, среди прочего, указатель на функцию процедуры обработки сигналов. Некоторые предопределенные сигналы (например, SIGKILL
) имеют заблокированное поведение, которое обрабатывается системой и не может быть переопределено такими системными вызовами.
сигактионная структура
[ редактировать ]Стандарт POSIX требует, чтобы структура sigaction была определена, как показано ниже, в заголовочном файле <signal.h> и содержала как минимум следующие поля:
struct sigaction {
void (*sa_handler)(int); /* address of signal handler */
sigset_t sa_mask; /* additional signals to block */
int sa_flags; /* signal options */
/* alternate signal handler */
void (*sa_sigaction)(int, siginfo_t *, void*);
};
Реализации могут свободно определять дополнительные, возможно, непереносимые поля. Член sa_handler указывает адрес функции, которая будет вызываться, когда процесс получает сигнал. Номер сигнала передается в эту функцию как целочисленный аргумент. Член sa_mask указывает дополнительные сигналы, которые будут блокироваться во время выполнения обработчика сигналов. sa_mask должен быть инициализирован с помощью sigemptyset(3). Член sa_flags указывает некоторые дополнительные флаги. sa_sigaction — альтернативный обработчик сигналов с другим набором параметров. Должен быть указан только один обработчик сигнала: sa_handler или sa_sigaction. Если желательно использовать sa_sigaction вместо sa_handler, необходимо установить флаг SA_SIGINFO.
Замена для signal()
[ редактировать ] The sigaction()
функция обеспечивает интерфейс для надежных сигналов вместо ненадежных signal()
функция. Обработчики сигналов, установленные signal()
интерфейс будет удален непосредственно перед выполнением обработчика. Поэтому постоянные обработчики должны быть переустановлены путем вызова signal()
во время выполнения обработчика, вызывая ненадежность в случае, если сигнал того же типа будет получен во время выполнения обработчика, но до переустановки. Обработчики, установленные sigaction()
интерфейс может быть установлен постоянно, а пользовательский набор сигналов может быть заблокирован во время выполнения обработчика. Эти сигналы будут разблокированы сразу после нормального завершения обработчика (но не в случае ненормального завершения, такого как выдача исключения C++).
Использование в С++
[ редактировать ]В С++ try {/* ... */} catch {/* ... */}
Структура программирования может быть (в зависимости от хост-платформы) основана на передаче сигналов. К catch
сигналы, преобразованные в исключения C++, на некоторых платформах, например, могут потребоваться специальные переключатели компилятора -fnon-call-exceptions
для GCC и компилятора Intel C. [1]
Пример
[ редактировать ]#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#define NUMCHLDS 10
void sigchld_handler(int, siginfo_t*, void*);
sig_atomic_t nexitedchlds = 0;
int
main(int argc, char *argv[])
{
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
sigemptyset(&act.sa_mask);
act.sa_sigaction = sigchld_handler;
act.sa_flags = SA_SIGINFO;
if (-1 == sigaction(SIGCHLD, &act, NULL))
{
perror("sigaction()");
exit(EXIT_FAILURE);
}
for (int i = 0; i < NUMCHLDS; i++)
{
switch(fork())
{
case 0:
/*
* Older OS implementations that do not correctly implement
* the siginfo structure will truncate the exit code
* by masking it with 0xFF.
*/
return 1234567890;
/* NOTREACHED */
case -1:
write(STDERR_FILENO, "fork ERROR!", 11);
exit(EXIT_FAILURE);
/* NOTREACHED */
default:
printf("Child created\n");
}
}
while (1)
{
if (nexitedchlds < NUMCHLDS)
pause();
else
exit(EXIT_SUCCESS);
}
/* NOTREACHED */
return 0;
}
void
sigchld_handler(int signo, siginfo_t *sinfo, void *context)
{
pid_t proc;
while ((proc = waitpid(-1, NULL, WNOHANG)) > 0)
{
/* signal main thread */
nexitedchlds++;
/*
* note: printf() is not signal-safe!
* don't use it in a signal handler.
* si_code is the full 32 bit exit code from the child (see also waitid()).
*/
printf("sinfo->si_pid = %ld\nproc = %ld\nexit code %d exit reason %d\n",
(long)sinfo->si_pid, (long)proc, sinfo->si_status, sinfo->si_code);
}
}
Ссылки
[ редактировать ]Внешние ссылки
[ редактировать ]- Единая спецификация UNIX , версия 4 от The Open Group : изучить и изменить действие сигнала – Справочник по системным интерфейсам,