Открыть сервис

Обработчик прерываний

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

История

Концепция прерываний возникла в ранних компьютерных системах 1950-х годов. Первоначально процессоры работали в режиме циклического опроса (polling), когда центральный процессор периодически проверял состояние каждого устройства ввода-вывода. Это приводило к неэффективному использованию вычислительных ресурсов, так как процессор тратил время на ожидание событий, которые могли не происходить.

В 1951 году в компьютере UNIVAC I была реализована система, позволяющая внешним устройствам сигнализировать процессору о необходимости обслуживания. Однако полноценный механизм прерываний с сохранением контекста и векторизацией появился в 1960-х годах, например, в мейнфреймах IBM System/360. В этих системах обработчики прерываний были организованы в виде таблицы векторов прерываний, где каждому типу прерывания соответствовал адрес его обработчика.

С развитием микропроцессоров (Intel 8080, 8086, Motorola 68000) механизм прерываний стал стандартным. В 1980-х годах операционные системы, такие как MS-DOS и Unix, начали активно использовать обработчики прерываний для управления драйверами устройств. В современных системах (Windows, Linux, macOS) обработчики прерываний интегрированы в ядро операционной системы и работают в контексте прерывания с минимальной задержкой.

Классификация обработчиков прерываний

Обработчики прерываний классифицируются по нескольким признакам.

По источнику прерывания

  • Аппаратные обработчики — обслуживают прерывания от внешних устройств (клавиатура, мышь, жёсткий диск, сетевая карта, таймер). Они вызываются сигналами от контроллера прерываний (например, Intel 8259A PIC или APIC).
  • Программные обработчики — обслуживают прерывания, инициированные программным обеспечением с помощью специальных инструкций процессора (например, INT в архитектуре x86). Используются для системных вызовов и обработки исключений (деление на ноль, нарушение защиты памяти).
  • Исключения (traps) — обрабатывают ошибки, возникающие в процессе выполнения инструкций (страничные ошибки, недопустимые опкоды). Они синхронны по отношению к текущему потоку выполнения.

По приоритету и маскированию

  • Маскируемые — могут быть временно заблокированы (замаскированы) путём установки флага прерывания в процессоре. Обычно это аппаратные прерывания от периферийных устройств.
  • Немаскируемые (NMI) — не могут быть заблокированы программно. Используются для критических событий, таких как сбой питания, ошибка памяти или аппаратный сброс.
  • Векторизованные — каждому прерыванию соответствует уникальный номер (вектор), который указывает на адрес обработчика в таблице векторов прерываний (IDT — Interrupt Descriptor Table). Это стандартный механизм в архитектурах x86, ARM, RISC-V.
  • Невекторизованные — все прерывания одного типа обслуживаются одним обработчиком, который самостоятельно определяет источник события (например, в старых системах с одним контроллером прерываний).

По времени выполнения

  • Верхняя половина (top half) — быстрый, атомарный код, выполняющий минимально необходимые действия (например, считывание данных из порта ввода-вывода или подтверждение приёма прерывания). Выполняется в контексте прерывания с запрещёнными другими прерываниями.
  • Нижняя половина (bottom half) — отложенная обработка, выполняемая в менее критичном контексте (например, в виде отложенных процедур (DPC) в Windows или tasklet/workqueue в Linux). Позволяет минимизировать время блокировки прерываний.

Устройство и механизм работы

Обработчик прерываний представляет собой последовательность машинных инструкций, адрес которой хранится в таблице векторов прерываний (IDT). При возникновении прерывания процессор выполняет следующие шаги:

  1. Сохранение контекста — на стек помещаются регистры состояния (флаги, счётчик команд) и, в зависимости от архитектуры, дополнительные регистры.
  2. Определение вектора — процессор считывает номер прерывания из шины данных (для аппаратных) или из инструкции (для программных) и обращается к IDT по этому номеру.
  3. Переход к обработчику — процессор загружает в счётчик команд адрес, хранящийся в соответствующей записи IDT, и начинает выполнение кода обработчика.
  4. Выполнение обработчика — обработчик выполняет необходимые действия: чтение/запись в порты устройств, обновление структур данных ядра, отправка сигналов процессам.
  5. Восстановление контекста — после завершения обработчик выполняет инструкцию возврата из прерывания (например, IRET в x86), которая восстанавливает сохранённые регистры и продолжает выполнение прерванной программы.

В многопроцессорных системах каждый процессор имеет собственную таблицу IDT, а контроллер прерываний (APIC) распределяет прерывания между ядрами для балансировки нагрузки.

Примеры обработчиков прерываний

Обработчик прерывания таймера (IRQ 0)

Один из наиболее часто срабатывающих обработчиков. В операционных системах общего назначения (Windows, Linux) он вызывается с частотой 100–1000 Гц. Обработчик выполняет следующие действия:

  • Увеличивает счётчик системного времени (jiffies).
  • Проверяет, не истекли ли таймеры процессов.
  • Инициирует перепланировку задач (вызов планировщика).
  • Обновляет статистику загрузки процессора.

Обработчик прерывания клавиатуры (IRQ 1)

При нажатии клавиши контроллер клавиатуры (8042) генерирует прерывание. Обработчик:

Обработчик страничной ошибки (исключение #PF)

Возникает при попытке доступа к виртуальной памяти, отсутствующей в физической памяти. Обработчик:

  • Проверяет, является ли адрес допустимым (находится ли он в адресном пространстве процесса).
  • Если допустим — загружает страницу с диска (подкачка) в физическую память.
  • Если недопустим — завершает процесс с ошибкой сегментации (SIGSEGV).

Применение

Обработчики прерываний используются в следующих областях:

  • Операционные системы — для управления драйверами устройств, планирования задач, обработки системных вызовов и исключений.
  • Встраиваемые системы — в микроконтроллерах (ARM Cortex-M, AVR, STM32) обработчики прерываний используются для обслуживания таймеров, датчиков, интерфейсов связи (UART, SPI, I2C).
  • Реального времени (RTOS) — в системах жёсткого реального времени обработчики прерываний должны иметь предсказуемое время выполнения для гарантии отклика.
  • Виртуализация — гипервизоры (KVM, Xen) перехватывают прерывания от гостевых операционных систем и обрабатывают их через собственные обработчики.

Критика и ограничения

Обработчики прерываний имеют ряд ограничений:

  • Время выполнения — обработчики должны выполняться максимально быстро, так как во время их работы другие прерывания могут быть заблокированы (особенно в однопроцессорных системах). Длительные обработчики могут привести к потере данных или пропуску событий.
  • Сложность отладки — обработчики работают в контексте прерывания, где недоступны многие механизмы ядра (например, блокировки, планирование). Ошибки в обработчиках могут привести к зависанию системы или краху.
  • Приоритетная инверсия — в многозадачных системах обработчик с низким приоритетом может блокировать высокоприоритетные задачи, если он удерживает ресурс.
  • Безопасность — некорректно написанные обработчики могут быть использованы для атак (например, переполнение буфера в драйвере, обрабатывающем прерывания).

Интересные факты

  • В архитектуре x86 количество векторов прерываний ограничено 256 (0–255). Из них первые 32 зарезервированы для исключений процессора (например, #DE — деление на ноль, #GP — общая защита).
  • В Linux обработчики прерываний регистрируются с помощью функции request_irq() и могут быть динамически назначены на любое ядро процессора через сродство прерываний (IRQ affinity).
  • В некоторых микроконтроллерах (например, ARM Cortex-M) обработчики прерываний могут быть написаны на языке высокого уровня (C/C++) без ассемблерных вставок, так как сохранение контекста выполняется аппаратно.
  • В операционной системе Windows обработчики прерываний работают на уровне IRQL (Interrupt Request Level), где более высокий уровень блокирует прерывания с более низким уровнем.

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →