sigaltstack(2) | System Calls Manual | sigaltstack(2) |
sigaltstack - считывает или устанавливает расположение стека сигналов
Standard C library (libc, -lc)
#include <signal.h>
int sigaltstack(const stack_t *_Nullable restrict ss, stack_t *_Nullable restrict old_ss);
sigaltstack():
_XOPEN_SOURCE >= 500 || /* начиная с glibc 2.12: */ _POSIX_C_SOURCE >= 200809L || /* glibc <= 2.19: */ _BSD_SOURCE
sigaltstack() allows a thread to define a new alternate signal stack and/or retrieve the state of an existing alternate signal stack. An alternate signal stack is used during the execution of a signal handler if the establishment of that handler (see sigaction(2)) requested it.
Обычный порядок действий для использования альтернативного стека сигналов:
Аргумент ss используется для указания нового альтернативного стека сигналов, а аргумент old_ss используется для получения информации об установленном в данный момент стеке сигналов. Если интересует какая-то одна из этих задач, то другой аргумент указывается как NULL.
Тип stack_t, используемый для аргументов этой функции, определён следующим образом:
typedef struct { void *ss_sp; /* базовый адрес стека */ int ss_flags; /* флаги */ size_t ss_size; /* количество байт в стеке */ } stack_t;
Для организации нового альтернативного стека сигналов поля этой структуры должны быть заполнены следующим образом:
Для отключения существующего стека, укажите в ss.ss_flags значение SS_DISABLE. В этом случае ядро игнорирует все флаги в ss.ss_flags и остальные поля в ss.
Если old_ss не равно NULL, то в нём возвращается информация об альтернативном стеке сигналов, который использовался до этого вызова sigaltstack(). В полях old_ss.ss_sp и old_ss.ss_size возвращаются начальный адрес и размер стека. В old_ss.ss_flags может быть возвращено одно из следующих значений:
Если присвоить ss значение NULL,а old_ss — не NULL, то можно получить текущие настройки альтернативного стека сигналов без его изменения.
При успешном выполнении sigaltstack() возвращается 0. В случае ошибки возвращается -1, а errno устанавливается в соответствующее значение.
Описание терминов данного раздела смотрите в attributes(7).
Интерфейс | Атрибут | Значение |
sigaltstack() | Безвредность в нитях | MT-Safe |
POSIX.1-2001, POSIX.1-2008, SUSv2, SVr4.
Флаг SS_AUTODISARM является расширением Linux.
The most common usage of an alternate signal stack is to handle the SIGSEGV signal that is generated if the space available for the standard stack is exhausted: in this case, a signal handler for SIGSEGV cannot be invoked on the standard stack; if we wish to handle it, we must use an alternate signal stack.
Establishing an alternate signal stack is useful if a thread expects that it may exhaust its standard stack. This may occur, for example, because the stack grows so large that it encounters the upwardly growing heap, or it reaches a limit established by a call to setrlimit(RLIMIT_STACK, &rlim). If the standard stack is exhausted, the kernel sends the thread a SIGSEGV signal. In these circumstances the only way to catch this signal is on an alternate signal stack.
На большинстве аппаратных архитектур, поддерживаемых Linux, стеки растут сверху вниз. Вызов sigaltstack() автоматически учтёт направление роста стека.
Functions called from a signal handler executing on an alternate signal stack will also use the alternate signal stack. (This also applies to any handlers invoked for other signals while the thread is executing on the alternate signal stack.) Unlike the standard stack, the system does not automatically extend the alternate signal stack. Exceeding the allocated size of the alternate signal stack will lead to unpredictable results.
A successful call to execve(2) removes any existing alternate signal stack. A child process created via fork(2) inherits a copy of its parent's alternate signal stack settings. The same is also true for a child process created using clone(2), unless the clone flags include CLONE_VM and do not include CLONE_VFORK, in which case any alternate signal stack that was established in the parent is disabled in the child process.
Вызов sigaltstack() заменяет устаревший вызов sigstack(). Для обратной совместимости в glibc также есть функция sigstack(). Во всех новых приложениях нужно использовать sigaltstack().
Системный вызов sigstack() появился в 4.2BSD. В нём использовалась слегка другая структура, и его главным недостатком было то, что вызывающий должен был учитывать направления роста стека.
В Linux 2.2 и старее в ss.sa_flags можно указывать только флаг SS_DISABLE. В версиях до ядра Linux 2.4 разрешалось sigaltstack() допускать ss.ss_flags==SS_ONSTACK с тем же смыслом как ss.ss_flags==0 (т. е., при включении SS_ONSTACK в ss.ss_flags ни к чему не приводило). В других реализациях и согласно POSIX.1 флаг SS_ONSTACK появляется в old_ss.ss_flags только как флаг результата. В Linux его не нужно даже указывать в ss.ss_flags, иначе это снизит переносимость, так как некоторые системы выдают ошибку, если в ss.ss_flags указан SS_ONSTACK.
В следующем сегменте кода показано использование sigaltstack() (и sigaction(2)) для установки альтернативного стека сигналов, который используется обработчиком для сигнала SIGSEGV:
stack_t ss; ss.ss_sp = malloc(SIGSTKSZ); if (ss.ss_sp == NULL) { perror("malloc"); exit(EXIT_FAILURE); } ss.ss_size = SIGSTKSZ; ss.ss_flags = 0; if (sigaltstack(&ss, NULL) == -1) { perror("sigaltstack"); exit(EXIT_FAILURE); } sa.sa_flags = SA_ONSTACK; sa.sa_handler = handler(); /* адрес обработчика сигналов */ sigemptyset(&sa.sa_mask); if (sigaction(SIGSEGV, &sa, NULL) == -1) { perror("sigaction"); exit(EXIT_FAILURE); }
execve(2), setrlimit(2), sigaction(2), siglongjmp(3), sigsetjmp(3), signal(7)
Русский перевод этой страницы руководства был сделан Alexander Golubev <fatzer2@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Hotellook, Nikita <zxcvbnm3230@mail.ru>, Spiros Georgaras <sng@hellug.gr>, Vladislav <ivladislavefimov@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>
Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.
Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.
5 февраля 2023 г. | Linux man-pages 6.03 |