0Pricing
C Academy · Урок

Сигналы

Асинхронные уведомления

«Сигналы» — бесплатный урок 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 — локальная установка не требуется.

Все уроки этого курса

  1. Каналы
  2. Разделяемая память
  3. Очереди сообщений
  4. Сигналы
← Назад к C Academy