Как обрабатывается прерывание в Linux?


35

Я просто знаю , что Interruptэто hardware signal assertionвызвано в процессоре штифтом. Но я хотел бы знать, как ОС Linux справляется с этим.
Что все происходит, когда происходит прерывание?


tldp.org/LDP/tlk/dd/interrupts.html объясняет все, что касается вопроса, который вы задали
Джон

Ответы:


40

Вот высокоуровневое представление низкоуровневой обработки. Я описываю простую типичную архитектуру, реальные архитектуры могут быть более сложными или отличаться способами, которые не имеют значения на этом уровне детализации.

Когда происходит прерывание , процессор смотрит, маскируются ли прерывания. Если они есть, ничего не происходит, пока они не будут разоблачены. Когда прерывания становятся не маскированными, и если есть какие-либо ожидающие прерывания, процессор выбирает одно.

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

Обработчик прерываний делает то, что должен, обычно посредством связи с периферийным устройством, которое инициировало прерывание для отправки или получения данных. Если прерывание было вызвано таймером, обработчик может запустить планировщик ОС, чтобы переключиться на другой поток. Когда обработчик заканчивает выполнение, он выполняет специальную инструкцию возврата из прерывания, которая восстанавливает сохраненные регистры и снимает маскировку прерываний.

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

  • «Верхняя половина» - это обработчик прерываний. Он выполняет необходимый минимум, обычно связывается с оборудованием и устанавливает флаг где-то в памяти ядра.
  • «Нижняя половина» выполняет любую другую необходимую обработку, например копирование данных в память процесса, обновление структур данных ядра и т. Д. Это может занять некоторое время и даже заблокировать ожидание какой-либо другой части системы, поскольку она работает с включенными прерываниями.

Как обычно по этой теме, для получения дополнительной информации прочитайте Драйверы устройств Linux ; Глава 10 о прерываниях.


22

Жиль уже описал общий случай прерывания, следующее относится конкретно к Linux 2.6 на архитектуре Intel (часть этого также основана на спецификациях Intel).

Прерывание - это событие, которое изменяет последовательность команд, выполняемых процессором.
Существует два вида прерываний:

  • Синхронное прерывание (исключение), создаваемое процессором при обработке инструкций
  • Асинхронное прерывание (Interrupt), выдаваемое другими аппаратными устройствами

Исключения вызваны ошибками программирования (ФЭ ошибка Divide , Page Fault , переполнение ) , которые должны быть обработаны ядром. Он посылает сигнал программе и пытается восстановиться после ошибки.

Следующие два исключения классифицируются:

  • Обнаруженное процессором исключение, сгенерированное ЦП при обнаружении аномального состояния; разделены на три группы: ошибки, как правило, могут быть исправлены, ловушки сообщают о выполнении, прерывания - серьезные ошибки.
  • Запрограммированное исключение, запрошенное программистом, обрабатывается как ловушка.

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

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

  • Прерывания могут произойти в любое время, ядро ​​пытается убрать его с дороги как можно скорее.
  • Прерывание может быть прервано другим прерыванием
  • В ядре есть области, которые вообще не должны прерываться

Определены два разных уровня прерывания:

  • Маскируемые прерывания, выдаваемые устройствами ввода / вывода; может быть в двух состояниях, в маске или без маски. Только немаскированные прерывания обрабатываются.
  • Немаскируемые прерывания ; критические неисправности (например, сбой оборудования); всегда обрабатывается процессором.

Каждое аппаратное устройство имеет свою собственную линию запроса прерывания (IRQ). IRQ нумеруются начиная с 0. Все линии IRQ подключены к программируемому контроллеру прерываний (PIC). PIC прослушивает IRQ и назначает их ЦПУ. Также возможно отключить конкретную линию IRQ.
Современные многопроцессорные системы Linux обычно включают в себя более новый Advanced PIC (APIC), который равномерно распределяет запросы IRQ между процессорами.

Промежуточным шагом между прерыванием или исключением и его обработкой является таблица дескрипторов прерываний (IDT). Эта таблица связывает каждый вектор прерывания или исключения (число) с указанным обработчиком (например, ошибка деления обрабатывается функцией divide_error()).

Благодаря IDT ядро ​​точно знает, как обрабатывать возникшие прерывания или исключения.


Итак, что же делает ядро ​​при возникновении прерывания?

  • Процессор проверяет после каждой инструкции, есть ли IRQ от (A) PIC
  • Если это так, консультируется с IDT для сопоставления полученного вектора с функцией
  • Проверяет, было ли прерывание выдано авторизованным источником
  • Сохраняет регистры прерванного процесса
  • Вызовите соответствующую функцию для обработки прерывания
  • Загрузите недавно сохраненные регистры прерванного процесса и попытайтесь возобновить его

Можете ли вы уточнить «Процессор проверяет после каждой инструкции, есть ли IRQ от (A) PIC» . Как именно это происходит? VIPСвязано ли это с -flag в регистре флагов или как? Заранее спасибо
red0ct

7

Прежде всего, участниками обработки прерываний являются периферийные аппаратные устройства, контроллер прерываний, процессор, ядро ​​операционной системы и драйверы. Периферийные аппаратные устройства отвечают за генерацию прерываний. Они утверждают строки запроса прерывания, когда хотят внимания от ядра операционной системы. Эти сигналы мультиплексируются контроллером прерываний, который отвечает за сбор сигналов прерываний. Он также отвечает за определение порядка, в котором сигналы прерывания будут передаваться в CPU. Контроллер прерываний может временно отключить определенную строку запроса прерывания (IRQL) и снова включить ее (маскировка IRQL). Контроллер прерываний передает собранные запросы на прерывание ЦП последовательно. CPU после завершения выполнения каждой команды CPU проверяет, есть ли ожидающие запросы прерывания от контроллера прерываний. Если ЦПУ обнаруживает, что имеется ожидающий запрос И флаг включения прерывания установлен во внутреннем регистре управления ЦП, то ЦПУ начинает обработку прерываний. Как вы можете видеть, манипулируя флагом прерывания в ЦП и связываясь с контроллером прерываний, ядро ​​Linux может контролировать принятие прерывания. Например, Linux может отключить прием прерываний от конкретного устройства или вообще запретить прием прерываний. Ядро Linux способно контролировать принятие прерываний. Например, Linux может отключить прием прерываний от конкретного устройства или вообще запретить прием прерываний. Ядро Linux способно контролировать принятие прерываний. Например, Linux может отключить прием прерываний от конкретного устройства или вообще запретить прием прерываний.

Что происходит, когда процессор получает запрос на прерывание? Во-первых, CPU автоматически отключает прерывания путем сброса флага прерываний. Они будут включены после завершения обработки прерываний. В то же время ЦП выполняет минимальный объем работы, необходимый для переключения ЦП из режима пользователя в режим ядра таким образом, чтобы он мог возобновить выполнение прерванного кода. CPU консультируется со специальными структурами управления CPU, заполненными ядром Linux, чтобы найти адрес кода, на который будет передано управление. Этот адрес является адресом первой инструкции обработчика прерываний, которая является частью ядра Linux.

В качестве первого шага обработки прерывания ядро ​​идентифицирует вектор полученного прерывания, чтобы определить, какое событие произошло в системе. Вектор прерывания определяет, какие действия предпримет Linux. В качестве второго шага Linux сохраняет остальные регистры процессора (которые не были сохранены процессором автоматически) и которые потенциально могут использоваться прерванной программой. Это очень важное действие, потому что оно позволяет Linux прозрачно обрабатывать прерывания относительно прерванной программы. В качестве третьего шага Linux завершает переключение в режим ядра, устанавливая среду ядра и устанавливая состояние процессора, необходимое для этого. И, наконец, вызывается вектор-зависимый обработчик прерываний. (Вы можете посмотреть макрос BUILD_INTERRUPT3 в arch \ x86 \ kernel \ entry_32. S, чтобы получить дополнительные подробности для примера, связанного с архитектурой x86) В случае периферийных устройств это процедура do_IRQ (). (Загляните в arch \ x86 \ kernel \ irq.c)

Зависимый от вектора обработчик прерываний обычно переносится вызовами irq_enter () и irq_exit (). Область кода, заключенная в паре этих функций, является атомарной по отношению к любым другим таким областям, а также атомарной по отношению к парам cli / sti. Irq_enter () и irq_exit () также собирают некоторую статистику, связанную с обработкой прерываний. Наконец, ядро ​​просматривает таблицу vector_irq, чтобы найти номер irq, назначенный вектору полученного прерывания, и вызвать handle_irq () (из arch \ x86 \ kernel \ irq_32.c).

На этом общая часть обработки прерываний в Linux заканчивается, потому что ядро ​​рассматривает зависимую от устройства подпрограмму обработчика прерываний, установленную драйвером устройства, как часть дескриптора irq и вызывает ее. Если такой обработчик не был установлен драйвером, ядро ​​просто подтверждает прерывание на контроллере прерываний и переходит к выходу из общего обработчика прерываний.

После окончания обработки прерывания ядро ​​восстанавливает состояние программы, которая была прервана ранее, и возобновляет выполнение этой программы.


CPU consults with special CPU control structures filled by Linux kernel to find an address of code to which control will be passed.Да! Интересно, что это за особые управляющие структуры ...
автомат

3

С точки зрения теории, почти все было объяснено. Но если вы ищете объяснение по структуре кода обработки прерываний ядра, вам следует перейти по следующей ссылке: Обход кода внутри обработки прерываний ядра

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.