Как отправить сигнал процессу в Linux с помощью C++?

«Как отправить сигнал процессу в Linux с помощью C++?» — вопрос из категории Linux и ОС, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Linux для отправки сигналов используется системный вызов kill() (из <csignal>). Основной способ:

#include <csignal>
#include <sys/types.h>
#include <unistd.h>
#include <iostream>

int main() {
    pid_t target_pid = 12345; // PID целевого процесса

    // 1. Отправка сигнала завершения (можно перехватить)
    if (kill(target_pid, SIGTERM) == -1) {
        perror("kill(SIGTERM) failed");
    }

    // 2. Отправка сигнала, который нельзя игнорировать (SIGKILL)
    // kill(target_pid, SIGKILL);

    // 3. Отправка сигнала текущему процессу
    raise(SIGUSR1); // Эквивалентно kill(getpid(), SIGUSR1)

    // 4. Проверка существования процесса (сигнал 0)
    if (kill(target_pid, 0) == 0) {
        std::cout << "Process " << target_pid << " exists and we have permission." << std::endl;
    } else {
        if (errno == ESRCH) {
            std::cout << "Process does not exist." << std::endl;
        } else if (errno == EPERM) {
            std::cout << "No permission to send signal." << std::endl;
        }
    }
    return 0;
}

Важные технические детали:

  • Права: Чтобы отправить сигнал, ваш процесс должен иметь соответствующие права (обычно быть владельцем процесса или иметь права root).
  • SIGKILL (9) и SIGSTOP (19): Эти сигналы не могут быть перехвачены, проигнорированы или заблокированы процессом-получателем.
  • Безопасность в многопоточных программах: В многопоточном приложении kill() отправляет сигнал всему процессу. Чтобы отправить сигнал конкретному потоку, используйте pthread_kill().
  • Более современный C++ интерфейс (C++11): Для управления сигналами внутри программы можно использовать std::signal, но для межпроцессного взаимодействия kill() остаётся стандартом.
  • Альтернативы сигналам: Для сложной межпроцессной коммуникации часто предпочтительнее использовать именованные каналы (FIFO), сокеты домена Unix (Unix domain sockets) или очереди сообщений POSIX, так как они более структурированы и надёжны.