Распределение IRQ в многопроцессорных системах

Linux придерживается модели симметричной многопроцессорной обработки SMP (Symmetric Multiprocessing). Это, в первую очередь, означает, что ядро не должно оказывать предпочтение одному процессору за счет других. Поэтому оно пытается распределить сигналы IRQ, поступающие от аппаратных устройств, среди всех процессоров по круговому принципу. В результате процессоры расходуют примерно одинаковую долю своего рабочего времени на обслуживание прерываний ввода/вывода.
Ранее в этой главе мы говорили, что в многоконтроллерной APIC-системе применяются довольно сложные механизмы динамического распределения IRQ-сигналов среди процессоров. Выполнение данных функций сродни процедурам, которые получает представительница прекрасного пола, посещая салон красоты. Здесь специалист оценивает тип кожи, состояние ресниц и т.д. (инициализация), после чего проводит соответствующие процедуры (выход из ситуаций).
На этапе начальной загрузки системы загружающий процессор выполняет функцию setup_io_APic_irqs о для инициализации чипа I/O APIC. Двадцать четыре записи таблицы переадресации прерываний этого чипа заполняются так, чтобы IRQ-сигналы от устройств ввода/вывода могли быть направлены любому процессору в системе в соответствии с принципом «наименьшего приоритета». Кроме того, на этапе начальной загрузки все процессоры выполняют функцию setup iocai APic (), ответственную за инициализацию локальных APIC-контроллеров. В частности, регистр приоритета задачи (регистр TPR) каждого чипа инициализируется некоторым фиксированным значением, свидетельствующим о том, что процессор готов обрабатывать IRQ — сигналы любого типа, независимо от приоритета. Ядро Linux не модифицирует это значение после своей инициализации.
Все регистры приоритетов задач содержат одинаковые значения, поэтому все процессоры имеют одинаковый приоритет. Для выхода из тупиковых ситуаций многоконтроллерная APIC-система использует значения в регистрах арбитражных приоритетов локальных APIC-контроллеров, о чем уже было сказано ранее. Поскольку такие значения автоматически меняются после каждого прерывания, IRQ-сигналы в большинстве случаев справедливо распределяются среди всех процессоров.
Короче говоря, когда аппаратное устройство возбуждает IRQ-сигнал, многоконтроллерная APIC-система выбирает один из процессоров и доставляет сигнал соответствующему локальному APIC-контроллеру, который, в свою очередь, прерывает свой процессор. Остальные процессоры не уведомляются об этом событии.
Все это, как по волшебству, выполняется аппаратной частью, и ядру не нужно ни о чем заботиться после инициализации многоконтроллерной APIC-системы. К сожалению, в некоторых случаях аппаратуре не удается распределить прерывания равномерно по всем микропроцессорам (например, такая проблема возникает у некоторых многопроцессорных материнских плат на базе Pentium 4). Поэтому в Linux 2.6 имеется специальный поток ядра kirqd, чтобы подкорректировать автоматическое распределение IRQ-запросов среди процессоров, когда это необходимо.