Сигналы
Асинхронные уведомления
«Сигналы» — бесплатный урок C Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C Academy содержит 4 уроков всего.
Что такое сигнал
Сигнал — это асинхронное уведомление, отправляемое процессу, чтобы сообщить о произошедшем событии, например нажатии пользователем Ctrl-C или завершении дочернего процесса. Сигналы представляют собой лёгкую форму IPC.
Распространённые сигналы
Вот несколько сигналов, с которыми Вы будете часто встречаться:
SIGINT— прерывание (Ctrl-C)SIGTERM— корректный запрос на завершениеSIGKILL— принудительное завершение (перехватить нельзя)SIGCHLD— дочерний процесс изменил состояниеSIGSEGV— недопустимый доступ к памяти
Действия по умолчанию
Для каждого сигнала предусмотрено действие по умолчанию: завершить работу, завершить работу с дампом памяти, игнорировать, приостановить или продолжить. Большинство этих действий можно переопределить с помощью обработчика.
Установка обработчика
Современный переносимый способ установить обработчик — sigaction. Обработчик — это функция, принимающая номер сигнала.
#include <signal.h>
#include <stdio.h>
void on_signal(int sig) {
/* note: printf is not async-signal-safe; for demo only */
write(1, "caught\n", 7);
}
int install(void) {
struct sigaction sa = {0};
sa.sa_handler = on_signal;
return sigaction(SIGINT, &sa, NULL);
}Почему не signal()
Старая функция signal() ведёт себя по-разному в разных системах (сбрасывает обработчик, не позволяет управлять SA_RESTART). Предпочитайте sigaction: её поведение чётко определено, и она переносима.
Функции, безопасные в асинхронных обработчиках сигналов
Обработчик может прервать ваш код в любой момент, поэтому ему разрешено вызывать только функции, безопасные в асинхронных обработчиках сигналов, например write. Вызов printf или malloc из обработчика может привести к взаимной блокировке или повреждению данных.
Использование volatile-флага
Безопасный шаблон: обработчик устанавливает флаг volatile sig_atomic_t, а основной цикл проверяет его. Так обработчик остаётся минимальным и безопасным.
#include <signal.h>
volatile sig_atomic_t stop = 0;
void handler(int sig) {
stop = 1; /* only set a flag */
}
/* main loop: while (!stop) { do_work(); } */Отправка сигналов
Используйте kill(pid, sig), чтобы отправить сигнал другому процессу, или raise(sig), чтобы отправить его самому себе. Несмотря на название, kill отправляет любой сигнал, а не только смертельные.
#include <signal.h>
int notify(int pid) {
return kill(pid, SIGTERM); /* ask process to terminate */
}Блокировка сигналов
Чтобы защитить критическую секцию, временно заблокируйте сигналы с помощью sigprocmask и набора сигналов. Заблокированные сигналы остаются ожидающими и доставляются после снятия блокировки.
#include <signal.h>
void block_int(void) {
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGINT);
sigprocmask(SIG_BLOCK, &set, NULL);
}Ожидание завершения дочерних процессов с помощью SIGCHLD
Когда дочерний процесс завершается, ядро отправляет сигнал SIGCHLD. Обработчик, вызывающий waitpid, забирает завершившийся дочерний процесс, предотвращая появление процессов-зомби, которые остаются в таблице процессов.
#include <signal.h>
#include <sys/wait.h>
void reap(int sig) {
while (waitpid(-1, NULL, WNOHANG) > 0)
; /* reap all finished children */
}Сигналы, которые нельзя перехватить
Два сигнала являются безусловными: SIGKILL всегда завершает процесс, а SIGSTOP всегда приостанавливает его. Их нельзя перехватить, заблокировать или проигнорировать, поэтому система гарантированно может управлять процессами.
Быстрая проверка
Проверьте, насколько хорошо вы поняли сигналы.
Итоги
Вы узнали о сигналах для асинхронного уведомления.
- Устанавливайте обработчики с помощью
sigaction, а не старой функцииsignal - Обработчики должны быть безопасными в асинхронном контексте; предпочтительно устанавливать флаг
- Отправляйте сигналы с помощью
kill/raise, а блокируйте с помощьюsigprocmask - Забирайте дочерние процессы при получении SIGCHLD; SIGKILL и SIGSTOP нельзя перехватить
Часто задаваемые вопросы
Урок «Сигналы» бесплатный?
Да — полный текст урока «Сигналы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C Academy, подпишись на CoddyKit PRO. Курс C Academy содержит 4 уроков всего.
Чему я научусь в уроке «Сигналы»?
Асинхронные уведомления Ты практикуешь C Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C Academy?
Предыдущий опыт не требуется. C Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Сигналы»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C Academy?
Да. Каждый урок C Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.