Ядро Linux в комментариях

       

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


Действительные обработчики прерываний для порта х86 тривиальны; на самом нижнем уровне они построены посредством многократного использования макроса BUILD_IRQ (строка ) для построения последовательностей небольших ассемблерных функций. Сам макрос BUILD_IRQ используется макросом BI (строка ), который в свою очередь используется макросом BUILD_16_IRQS (строка ), который в строках с по применяется для создания подпрограмм ассемблера. Эта последовательность вызовов макросов предназначена всего лишь для уменьшения объема и избыточности действительного кода, который должен быть написан— вместо 16 применений макроса BUILD_16_IRQS могло бы потребоваться 256 обращений к макросу BUILD_IRQ.

Подпрограммы ассемблера выглядят подобно следующему:

IRQ0x00_interrupt: pushl 0x00-256 jmp common_interrupt

Т.е. каждая из них просто выталкивает свой номер IRQ (минус 256, по причинам, которые описаны в стоке ) в стек, а затем выполняет переход к общей подпрограмме прерывания.

Общая подпрограмма прерывания называется common_interrupt и также является короткой. Она образована макросом BUILD_COMMON_IRQ (строка ) и просто вызывает функцию do_IRQ, обеспечив, чтобы та выполнила возврат к функции ret_from_intr (строка ), являющейся частью подпрограммы system_call, которая была исследована в . Функция do_IRQ, которая вскоре будет рассмотрена, принимает на себя ответственность проследить за тем, чтобы прерывания были обслужены.

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

  • Центральный процессор выполняет переход к подпрограмме IRQxNN (где NN — номер прерывания), которая выталкивает свой уникальный номер в стек, а затем выполняет переход к common_interrupt.
  • Подпрограмма common_interrupt вызывает функцию do_IRQ и следит за тем, чтобы при возврате из нее управление было передано функции ret_from_intr.
  • Функция do_IRQ вызывает код, который является характерным для чипа контроллера прерываний — код, который при необходимости обращается непосредственно к чипу и обслуживает прерывание. Для чипа контроллера 8259А, имеющего наибольшее распространение в архитектурах PC, функцией обработчика является do_8259A_IRQ, которая и используется здесь для примера.
  • Функция do_8259A_IRQ временно отключает конкретное прерывание, подлежащее обслуживанию, вызывает функцию handle_IRQ_event и затем снова включает этот отдельный IRQ.
  • Функция handle_IRQ_event включает прерывания для медленных IRQ или оставляет их отключенными для быстрых IRQ. Затем она просматривает очередь функций, которые были связаны с этим IRQ, поочередно вызывая их. Поскольку IRQ включены для медленных IRQ, именно здесь обработчик медленных IRQ может быть прерван другим прерыванием. После того, как очередь функций исчерпана, функция handle_IRQ_event отключает прерывания и выполняет возврат к характерной для контроллера функции обработчика, которая выполняет возврат к функции do_IRQ.
  • Функция do_IRQ обслуживает любые ожидающие обработки нижние половины, а затем выполняет возврат. Как вы уже знаете, это возврат к функции ret_from_intr. Происходящее в дальнейшем освещено в .


  • Содержание раздела