Объяснение функции __do_IRQ

#c #linux #linux-kernel #interrupt-handling

#c #linux #linux-ядро #обработка прерываний

Вопрос:

Я готовлю презентацию о том, как ядро Linux обрабатывает прерывания, основываясь на книге Понимание ядра Linux ny Bovet amp; Cesati. На обложке указано, что она охватывает версию 2.6. Однако я не совсем понимаю, как должна работать данная функция __do_IRQ(). Хотя я немного (базово) программировал на C, я не могу понять некоторые инструкции.

     spin_lock(amp;(irq_desc[irq].lock));
    irq_desc[irq].handler->ack(irq);
    irq_desc[irq].status amp;= ~(IRQ_REPLAY | IRQ_WAITING);
    irq_desc[irq].status |= IRQ_PENDING;
    if (!(irq_desc[irq].status amp; (IRQ_DISABLED | IRQ_INPROGRESS)) amp;amp; irq_desc[irq].action){
irq_desc[irq].status |= IRQ_INPROGRESS;
    do{
     irq_desc[irq].status amp;= ~IRQ_PENDING;
     spin_unlock(amp;(irq_desc[irq].lock));
     handle_IRQ_event(irq,regs,irq_desc[irq].action);
     spin_lock(amp;(irq_desc[irq].lock));
   }while (irq_desc[irq].status amp; IRQ_PENDING);
   irq_desc[irq].status amp;= ~IRQ_INPROGRESS;
}
   irq_desc[irq].handler->end(irq);
   spin_unlock(amp;(irq_desc[irq].lock));
  

Мои вопросы заключаются в следующем:

  1. Как работает присвоение .status ? В книге говорится, что это набор флагов. Я понимаю, что флаги являются переменными в верхнем регистре, но как к ним получить доступ в этом сценарии? Разве это не должно быть .status.IRQ_SOMETHING или что-то в этом роде?

  2. Что означает единственное «amp;» в условии выражения if?

Комментарии:

1. Разве этот вопрос не просто задает вопрос «что такое операторы в C»?

2. Прочитайте это руководство по битовым манипуляциям в C или выполните поиск в Google по этой теме.

Ответ №1:

Я собираюсь ответить в обратном порядке.

amp; Это оператор «побитовое И»; точно так | же, как и оператор «побитовое ИЛИ». Учитывая целочисленную переменную x , выражение:

   x |= (1U << n);
  

Устанавливает бит n x в 1 значение . Наоборот:

   x amp;= ~(1U << n);
  

Очищает бит n x , устанавливая его 0 равным .

Получив представление об этом операторе, вы можете увидеть, как .status работает поле — это целочисленное поле, и различные флаги включаются и выключаются с помощью упомянутых выше операторов. Флаги проверяются с помощью amp; оператора:

   irq_desc[irq].status amp; (IRQ_DISABLED | IRQ_INPROGRESS)
  

Выдает истинный результат, когда IRQ_DISABLED IRQ_INPROGRESS в поле установлен любой из битов или .status .