Прерывания и исключения в Linux

Прерывание обычно определяется как событие, меняющее последовательность инструкций, выполняемых процессором.
Прерывания часто подразделяются на синхронные и асинхронные:
- синхронные прерывания выдаются управляющим блоком процессора при выполнении инструкций и называются синхронными, потому что управляющий блок процессора выдает их только по окончании выполнения инструкции;
- асинхронные прерывания генерируются другими аппаратными устройствами в произвольные моменты времени по отношению к тактовым сигналам процессора.
В руководствах по микропроцессорам Intel синхронные и асинхронные прерывания обозначаются терминами «исключения» и «прерывания» соответственно.
Обработка прерываний является для ядра одной из задач, требующих исключительно тонкого подхода, потому что она должна удовлетворять следующим ограничениям:
Прерывания могут поступать в любой момент, например, когда ядро заканчивает какую-то операцию. Следовательно, цель ядра в том, чтобы как можно скорее убрать прерывание с дороги и отложить выполнение связанных с прерыванием действий, насколько это возможно. Например, предположим, что по сети прибыл блок данных. Когда устройство прервет ядро, последнее может просто отметить у себя наличие данных и позволить процессору доделать то, что он выполнял перед этим, а остальные действия, касающиеся данных (копирование их в буфер процесса-получателя и запуск самого процесса), выполнить позже. Таким образом, действия, совершаемые ядром в ответ на прерывание, делятся на неотложные, которые ядро выполняет сразу, и на те, которые можно оставить на потом.
Поскольку прерывания могут поступать в любой момент, возможна ситуация, когда во время обработки одного прерывания возникает второе (имеющее другой тип). Такой подход оправдан, потому что он позволяет поддерживать занятость устройств ввода/вывода. Иными словами, обработчик прерываний должен быть написан так, чтобы соответствующие части ядра могли быть выполнены вложенным образом. Когда завершится последний обработчик, ядро должно быть в состоянии возобновить выполнение прерванного процесса или переключиться на другой процесс, если сигнал прерывания вызвал активность планировщика.
Хотя ядро может принять новый сигнал прерывания во время обработки предыдущего, в коде ядра имеются критические области, в которых прерывания должны быть отключены.
Ошибки в общем случае могут быть исправлены; после их исправления программе разрешается работать дальше без потери целостности. Сохраненное значение регистра eip является адресом инструкции, вызвавшей ошибку, и, следовательно, эта инструкция может быть выполнена снова, когда обработчик исключения возвратит управление. Ловушки срабатывают сразу после выполнения соответствующей инструкции. После того как ядро возвратит управление программе, ей разрешается работать дальше без потери целостности. Сохраненное значение регистра eip является адресом инструкции, которая должна быть выполнена после инструкции, вызвавшей это исключение. Ловушки применяются, в основном, для целей отладки. Роль сигнала прерывания в данном случае сводится к уведомлению отладчика о выполнении конкретной инструкции (например, в программе достигнута точка останова). IP адрес инструкции, вызвавшей исключение. Аварии применяются для индикации серьезных ошибок, таких как сбои аппаратной части или противоречивые данные в системных таблицах. Сигнал прерывания, посылаемый управляющим блоком, является тревожным сигналом, используемым для передачи управления соответствующему обработчику исключений - аварий. У этого обработчика нет иного выбора, кроме принудительного завершения проблемного процесса.