Предположим, что есть две программы. Одна программа должна передать другой большое количество данных - через файл.
Работает эта история таким образом, что одна программа открывает файл (на запись) и передает данные, другая открывает его же (на чтение) и получает инфу.
Проблема заключается в том, что вторая программа должна как-то узнать о том, что пришло время считывать данные.
Как реализовать процесс уведомления? Ну, можно через сигналы)
Сигнал — это механизм оповещения процесса о том, что произошло некое событие.
Иногда они описываются, как программные прерывания, т.к. приостанавливают нормальное выполнение программы.
Один процесс может отправить сигнал другому с помощью системного вызова kill(), который является аналогом команды оболочки kill:
#include <signal.h>
int kill(pid_t pid, int sig);
Важно понимать, что сигналы доставляются процессам через ядро операционки:
процесс_1 -> ядро -> процесс_2
Каждому сигналу присваивается уникальный идентификатор — целое число, начиная с 1. Эти числа определены в файле <signal.h>. Каждому номеру соответствует символьное обозначение.
В удобном формате посмотреть список сигналов можно с помощью команды "kill -l":
$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
Сигналы можно разделить на две большие категории:
1) стандартные - используются ядром для оповещения процессов о свершении событий.
В Linux стандартные сигналы пронумерованы от 1 до 31;
2) сигналы реального времени - обычно используются для коммуникации между процессами или потоками.
В отличие от стандартных, у сигналов реального времени нет заранее определённых имён.
Они идентифицируются выражением вида (SIGRTMIN + n), где n — это целое число от 0 до (SIGRTMAX – SIGRTMIN):
$ kill -l
34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2
...
Сигналы реального времени пронумерованы от 34 до 64: SIGRTMIN -> SIGRTMAX:
#include <stdio.h>
#include <signal.h>
int main() {
printf("SIGRTMIN: %d\n", SIGRTMIN);
printf("SIGRTMAX: %d\n", SIGRTMAX);
return 0;
}
SIGRTMIN: 34
SIGRTMAX: 64
В ответ на сигнал, процесс либо выполняет заранее определенное действие (приостановка, завершение, возобновление работы), либо происходит перехват и отработка кастомного вызова, либо 0 реакции - игнор.
Игнорировать процесс может и сигналы, к которым подвязано какое-то действие. Реализуется это через определение сигнальной маски.
Таким образом мы гарантируем то, что выполнение фрагмента кода не будет прервано доставкой сигнала.
Linux++ | IT-Образование
