То, как ядро «вызывает» обработчик сигнала, прерывает поток, сохраняя маску сигнала и состояние процессора в структуре ucontext_t
в стеке, который находится чуть дальше (ниже, при реализации с увеличением) стека прерванного кодауказатель и возобновление выполнения по адресу обработчика сигнала.Ядру не нужно отслеживать какое-либо состояние «этот процесс находится в обработчике сигнала»;это полностью следствие нового созданного кадра вызова.
Если прерванный поток находился в середине системного вызова, ядро вернется из кода пространства ядра и отрегулирует адрес возврата, чтобы повторить системуcall (если для сигнала установлено SA_RESTART
, а системный вызов перезапускаемый) или в коде возврата (если не перезапускается) EINTR
.
Следует отметить, что longjmp
Асинхр-сигнал небезопасным.Это означает, что он вызывает неопределенное поведение, если вы вызываете его из обработчика сигнала, если сигнал прервал другую асинхронную небезопасную функцию.Но до тех пор, пока прерванный код не использует библиотечные функции или использует библиотечные функции, помеченные как async-signal-safe, разрешается вызывать longjmp
из обработчика сигнала.
Наконец, мой ответна основе POSIX, поскольку вопрос помечен unix
.Если бы вопрос был только о чистом C, я подозреваю, что ответ несколько иной, но сигналы без POSIX все равно бесполезны ...