Реализация системы обработки прерываний
Реализация системы обработки прерываний
Возможно, не вызовет удивления, что реализация системы обработки прерываний в операционной системе Linux очень сильно зависит от аппаратной платформы. Она зависит от типа процессора, типа контроллера прерываний, особенностей аппаратной платформы и устройства самой вычислительной машины.
На рис. 6.1 показана диаграмма пути, который проходит запрос на прерывание в аппаратном обеспечении и в ядре.
Рис. 6.1. Прохождение запроса на прерывание в аппаратном обеспечении и в ядре
Устройство инициирует прерывание путем отправки электрического сигнала контроллеру прерывания по аппаратной шине. Если соответствующая линия запроса на прерывание не запрещена (линия может быть в данный момент времени замаскирована), то контроллер прерываний отправляет прерывание процессору. Для большинства аппаратных платформ это осуществляется путем подачи сигнала на специальный вывод процессора. Если прерывания не запрещены в процессоре (может случиться, что они запрещены), то процессор немедленно прекращает ту работу, которую он выполнял, запрещает систему прерываний, осуществляет переход на специальный предопределенный адрес памяти и начинает выполнять программный код, который находится по этому адресу. Этот предопределенный адрес памяти устанавливается ядром и является точкой входа в обработчики прерываний.
Прохождение прерывания в ядре начинается из жестко определенной точки входа, так же как и в случае системных вызовов. Для каждой линии прерывания существует своя уникальная точка, куда переходит процессор. Именно этим способом ядро получает информацию о номере IRQ приходящего прерывания. В точке входа сначала в стеке ядра сохраняется значение номера прерывания и значения всех регистров процессора (которые соответствуют прерванному заданию). После этого ядро вызывает функцию do_IRQ(). Далее, начиная с этого момента, почти весь код обработки прерываний написан на языке программирования С, хотя несмотря на это код все же остается зависимым от аппаратной платформы.
Функция do_IRQ() определена следующим образом.
unsigned int do_IRQ(struct pt_regs regs);
Так как соглашение о вызовах функций в языке С предусматривает сохранение аргументов функций в вершине стека, то структура pt_regs содержит первоначальные значения всех регистров процессора, которые были сохранены ассемблерной подпрограммой в точке входа. Так как значение номера прерывания также сохраняется, то функция do_IRQ() может это значение восстановить. Для аппаратной платформы x86 код будет следующим.
int irq = regs.orig_eax & 0xff;
После вычисления значения номера линии прерывания, функция do_IRQ() отправляет уведомление о получении прерывания и запрещает доставку прерываний с данной линии. Для обычных машин платформы PC, эти действия выполняются с помощью функции mask_and_ack_8295A(), которую вызывает функция do_IRQ(). Далее функция do_IRQ() выполняет проверку, что для данной линии прерывания зарегистрирован правильный обработчик прерывания, что этот обработчик разрешен и что он не выполняется в данный момент. Если все эти условия выполнены, то вызывается функция handle_IRQ_event(), которая выполняет установленные для данной линии обработчики прерывания. Для аппаратной платформы x86 функция handle_IRQ_event() имеет следующий вид.
int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
struct irqaction *action) {
int status = 1;
if (!(action->flags & SA_INTERRUPT))
local_irq_enable();
do {
status != action->flags;
action->chandler(irq, action->dev_id, regs);
action = action->next;
} while (action);
if (status & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
local_irq_disable();
return status;
}
Так как процессор запретил прерывания, они снова разрешаются, если не указан флаг SA_INTERRUPT при регистрации обработчика. Вспомним, что флаг SA_INTERRUPT указывает, что обработчик должен выполняться при всех запрещенных прерываниях. Далее в цикле вызываются все потенциальные обработчики прерываний. Если эта линия не является совместно используемой, то цикл заканчивается после первой итерации. В противном случае вызываются все обработчики. После этого вызывается функция add_interrupt_randomness(), если при регистрации указан флаг SA_SAMPLE_RANDOM. Данная функция использует временные характеристики прерывания, чтобы сгенерировать значение энтропии для генератора случайных чисел. В приложении Б, "Генератор случайных чисел ядра", приведена более подробная информация о генераторе случайных чисел ядра.
В конце прерывания снова запрещаются (для функции do_IRQ() требуется, чтобы прерывания были запрещены). Функция do_IRQ() производит очистку стека и возврат к первоначальной точке входа, откуда осуществляется переход к функции ret_from_intr().
Функция ret_from_intr(), так же как и код входа, написана на языке ассемблера. Эта функция проверяет, есть ли ожидающий запрос на перепланирование выполнения процессов (следует вспомнить главу 4, "Планирование выполнения процессов", и флаг need_resched). Если есть запрос на перепланирование и ядро должно передать управление в пространство пользователя (т.е. прерывание прервало работу пользовательского процесса), то вызывается функция schedule(). Если возврат производится в пространство ядра (т.е. прерывание прервало работу кода ядра), то функция schedule() вызывается, только если значение счетчика preempt_count равно нулю (в противном случае небезопасно производить вытеснение кода ядра), После возврата из функции schedule() или если нет никакой ожидающей работы, восстанавливаются первоначальные значения регистров процессора и ядро продолжает работу там, где оно было прервано.
Для платформы x86, подпрограммы, написанные на языке ассемблера, находятся в файле arch/i386/kernel/entry.S, а соответствующие функции на языке С — в файле arch/i386/kernel/irq.с. Для других поддерживаемых аппаратных платформ имеются аналогичные файлы.
Интерфейс /proc/interrupts
Файловая система procfs — это виртуальная файловая система, которая существует только в памяти ядра и обычно монтируется на каталог /proc. Чтение или запись файлов на файловой системе procfs приводит к вызовам функций ядра, которые имитируют чтение или запись обычных файлов. Важный пример — это файл /proc/interrupts, который содержит статистику, связанную с прерываниями в системе, Ниже приведен пример вывода из этого файла на однопроцессорном персональном компьютере.
CPU0
0: 3602371 XT-PIC timer
1: 3048 XT-PIC i8042
2: 0 XT-PIC cascade
4: 2689466 XT-PIC uhci-hcd, eth0
5: 0 XT-PIC EMU10K1
12: 85077 XT-PIC uhci-hcd
15: 24571 XT-PIC aic7xxx
NMI: 0
LOC: 3602236
ERR: 0
Первая колонка содержит названия линий прерывания. В показанной системе присутствуют линии прерываний с номерами 0–2, 4, 5, 12 и 15. Линии, для которых не инсталлирован обработчик, не показываются. Вторая колонка — это количество запросов на прерывания с данным номером. В действительности такая колонка является отдельной для каждого процессора, но в данной машине только один процессор.
Как легко видеть, обработчик прерываний таймера получил 3.602.371[32] запрос на прерывание, в то время как обработчик прерываний звукового адаптера (EMU10K1) не получил ни одного прерывания (это говорит о том, что он не использовался с того момента, как машина была загружена). Третья колонка— это контроллер прерываний, который обслуживает данное прерывание. Значение XT-PIC соответствует программируемому контроллеру прерываний PC (PC programmable interrupt controller). Для систем с устройством I/О APIC для большинства прерываний в качестве контроллера прерываний будет указано значение IO-APIC-level или IO-APIC-edge. И наконец, последняя колонка — это устройство, которое связано с прерыванием. Имя устройства указывается в параметре dev_name при вызове функции request_irq(), как обсуждалось ранее. Если прерывание используется совместно, как в случае прерывания номер 4 в этом примере, то перечисляются все устройства, зарегистрированные на данной линии прерывания.
Для любопытствующих, код, связанный с файловой системой procfs, находится в файле fs/proc. Функция, которая обеспечивает работу интерфейса /proc/interrupts, называется show_interrupts() и является зависимой от аппаратной платформы.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
Обработчики прерываний
Обработчики прерываний Функция, которую выполняет ядро в ответ на определенное прерывание, называется обработчиком прерывания (interrupt handler) или подпрограммой обслуживания прерывания (interrupt service routine). Каждому устройству, которое генерирует прерывания, соответствует свой
Запрещение и разрешение прерываний
Запрещение и разрешение прерываний Для локального запрещения прерываний на текущем процессоре (и только на текущем процессоре) и последующего разрешения можно использовать следующий код.local_irq_disable();/* прерывания запрещены ... */local_irq_enable();Эти функции обычно реализуются в
Состояние системы обработки прерываний
Состояние системы обработки прерываний Часто необходимо знать состояние системы обработки прерываний (например, прерывания запрещены или разрешены, выполняется ли текущий код в контексте прерывания или в контексте процесса).Макрос irq_disabled(), который определен в файле
Механизм отложенных прерываний (softirq)
Механизм отложенных прерываний (softirq) Обсуждение существующих методов обработки нижних половин начнем с механизма softirq. Обработчики на основе механизма отложенных прерываний используются редко. Тасклеты — это более часто используемая форма обработчика нижних половин.
Реализация отложенных прерываний
Реализация отложенных прерываний Отложенные прерывания определяются статически во время компиляции. В отличие от тасклетов, нельзя динамически создать или освободить отложенное прерывание. Отложенные прерывания представлены с помощью структур softirq_action, определенных
Использование отложенных прерываний
Использование отложенных прерываний Отложенные прерывания зарезервированы для наиболее важных и критичных ко времени выполнения обработчиков нижних половин в системе. Сейчас только две подсистемы — подсистема SCSI и сетевая подсистема — напрямую используют механизм
Обработчик прерываний таймера
Обработчик прерываний таймера Теперь, когда мы разобрались, что такое jiffies и HZ, а также какова роль системного таймера, рассмотрим реализацию обработчика прерываний системного таймера. Обработчик прерываний таймера разбит на две части: часть, зависимую от аппаратной
Источники прерываний таймера
Источники прерываний таймера На этом мы, пожалуй, закончим наш краткий экскурс по стране таймеров и перейдем к вещам, которые уже не так очевидны.Откуда возникают прерывания таймера? На рисунке ниже приведены аппаратные компоненты (и некоторые характерные для PC значения
Написание обработчиков прерываний
Написание обработчиков прерываний Давайте посмотрим, как настроить обработчики прерываний — вызовы, характеристики и кое-какие стратегии
Подключение обработчиков прерываний
Подключение обработчиков прерываний Для подключения к источнику прерывания воспользуйтесь функцией InterruptAttach() или InterruptAttachEvent().#include <sys/neutrino.h>int InterruptAttachEvent(int intr, const struct sigevent *event, unsigned flags);int InterruptAttach(int intr, const struct sigevent* (*handler)(void *area, int id), const void *area, int size, unsigned flags);Параметр
Обработчики прерываний
Обработчики прерываний Обработчики прерываний в QNX4 могли либо возвратить идентификатор прокси (указывая этим, что надо переключить прокси и таким образом уведомить ее владельца о прерывании), либо возвратить нуль (что означало бы, что в дальнейшем ничего делать не
Обработка прерываний таймера
Обработка прерываний таймера Каждый компьютер имеет аппаратный таймер или системные часы, которые генерируют аппаратное прерывание через фиксированные интервалы времени. Временной интервал между соседними прерываниями называется тиком процессора или просто тиком (CPU
9.2.3.2 Обработка прерываний по отказу системы защиты
9.2.3.2 Обработка прерываний по отказу системы защиты Вторым типом отказа, встречающегося при обращении к странице, является отказ системы защиты, который означает, что процесс обратился к существующей странице памяти, но судя по разрядам, описывающим права доступа к
10.1.3 Программы обработки прерываний
10.1.3 Программы обработки прерываний Как уже говорилось выше (раздел 6.4.1), возникновение прерывания побуждает ядро запускать программу обработки прерываний, в основе алгоритма которой лежит соотношение между устройством, вызвавшим прерывание, и смещением в таблице
Обработчики прерываний
Обработчики прерываний Везде, кроме последней главы, все, что мы пока делали в ядре, сводилось к запросам и ответам разным процессам или работали со специальными файлом, посылали ioctl или выдавали системный вызов. Но работа ядра не должна сводится только к обработке
Перенаправление прерываний
Перенаправление прерываний Начнем с попытки устранить самое неприятное из возможных прерываний: к вам обращаются с проблемой, которую должен решить кто-то другой. Может быть, поступим так:— Том, проблема с веб-сервером.— Отлично! Сообщи мне о результатах, когда