Skip to content

Latest commit

 

History

History
65 lines (53 loc) · 5.48 KB

File metadata and controls

65 lines (53 loc) · 5.48 KB

Сигналы Linux

Сигналы — короткое сообщение, посылаемое процессу, или группе процессов, чтобы:

  • Уведомить об определённом событии.
  • Заставить выполнить обработчик сигнала.

По мимо обычных сигналов, есть сигналы реального времени, их отличие от обычных, что они всегда ставятся в очередь, а потому процесс сможет их все обработать, в то время как с обычными сигналами не всегда.

Системные вызовы отправки сигнала:

  • kill( ) — Send a signal to a thread group.
  • tkill( ) — Send a signal to a process.
  • tgkill( ) — Send a signal to a process in a specific thread group.
  • sigaction( ) — Change the action associated with a signal.
  • signal( ) — Similar to sigaction( ).
  • sigpending( ) — Check whether there are pending signals. (Проверка необработанных сигналов)
  • sigprocmask( ) — Modify the set of blocked signals(заблокированных сигналов).
  • sigsuspend( ) — Wait for a signal

Нужно разделять 2 задачи: отправка и обработка сигнала ядром. Каждая из этих задач требует отдельного подхода:

  • Генерация сигнала — ядро изменяет структуру данных процесса, что означает отправку сигнала.
  • Доставка сигнала — реакция на сигнал, которая может наступить далеко не сразу. Например, потому что процесс заблокировал обработку сигнала, или потому что мы уже в обработчике данного сигнала, обработчики обычных сигналов не должны быть рентабельными.

Реакция на доставленный сигнал

Реакция на доставленный сигнал зависит от ситуации и сигнала:

  • Игнорирование сигнала, не каждый сигнал может быть проигнорирован, например, SIGKILL, SIGSTOP.
  • Выполнить действие по умолчанию: завершить выполнение, сделать дамп, игнорировать, остановить, возобновить исполнение.
  • Вызвать обработчик сигнала. Не для всех сигналов можно назначить свой обработчик сигнала.

Генерация сигнала

Для отправки сигнала нужен системный вызов sys_kill(). Когда он завершается, это значит только, что сигнал отправлен и больше ничего. Далее находится pid и соответсвующий task_struct. После чего, зовётся kik_task() - функция, которая будет процесс, и начинается этап доставки сигнала. (!TODO)

Доставка сигнала

Чтобы обработать сигналы вызывается функция — do_signal(). Обработка сигнала откладывается прямо до возвращения в пользовательский режим, потому что только в этот момент есть гарантия того, что все lock’и отпущены и структуры данных свободны. Если для сигнала был задан обработчик, то do_signal() должна его позвать. Но тут всё не просто в работе со стеком.

Последовательность действий:

  1. Перед возвращение в пользовательский режим ядро зовёт функцию — do_signal().
  2. Которая обрабатывает сигнал, вызывая handle_signal(), которая настраивает стэк режима пользователя, вызывая setup_frame(), который копирует стэк аппаратного режима в стэк пользователя и записывает адрес завершающей функции sys_sigreturn.
  3. По возвращению в процесс пользователя, он начинает обработку сигнала, так как rip = handler.
  4. Когда обработчик завершиться на вершине стока будет адрес кода, который был помещён туда функцией setup_frame() и который должен быть выполнен после обработки сигнала.
  5. Выполнить системный вызов, вызывающий функцию sys_sigreturn, которая восстанавливает первоначальный контекст.

Повторное выполнение системных вызовов (!TODO) restartable call uses - restart_block - on task_struct - number of system call and parameters.