Метод опроса или прерывания - PullRequest
37 голосов
/ 19 июня 2010

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

Ответы [ 14 ]

57 голосов
/ 19 июня 2010

Если интересующее событие:

  1. Асинхронный
  2. Срочное
  3. Infrequent

тогда обработчик на основе прерываний будет иметь смысл.

Если интересующее событие:

  1. Синхронный (т.е. вы знаете, когда ожидать этого в небольшом окне)
  2. Не срочно (т. Е. Медленный интервал опроса не оказывает вредного воздействия)
  3. Частый (то есть большинство ваших циклов опроса создают «хит»)

тогда опрос мог бы быть лучше.

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

15 голосов
/ 19 июня 2010

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

8 голосов
/ 22 июня 2010

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

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

В этом примере подпрограмма прерывания реагирует на прояснение лазерного луча и настраивается на событие, когда он блокируется:

   BEAM_INTR_EN = TRUE;   /*re-enable the beam interrupts*/

   /*Set the beam interrupt for the next clear to blocked event*/
   BEAM_INTR_EDGE = CLEAR_TO_BLOCKED;
   BEAM_INTR_FLAG = FALSE; /*Clear the interrupt*/

У этого кода есть 2 слабых места: 1) Если лазерный луч снова заблокировался перед сбросом флага прерывания (BEAM_INTR_FLAG = FALSE;). Прерывание будет пропущено, и код будет не синхронизирован с состоянием лазерного луча.

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

Самый простой способ исправить 1) - дважды проверить после настройки прерывания, если оно произошло, форсировать прерывание. Для исправления 2) переместите включение прерываний после двойной проверки:

   /*Set the beam interrupt for the next clear to blocked event*/
   BEAM_INTR_EDGE = CLEAR_TO_BLOCKED;
   BEAM_INTR_FLAG = FALSE; /*Clear the interrupt*/

   /*Double check beam state to see if it has already gone blocked*/
   if (BEAM_STATE == BEAM_BLOCKED)
   {
      BEAM_INTR_FLAG = TRUE; /*Force the interrupt to re-enter the ISR after exiting*/
   }
   BEAM_INTR_EN = TRUE;    /*re-enable the beam interrupts*/

Форсирование прерывания заставляет систему работать с одним и тем же конечным автоматом, просто принудительно его округляя вручную, чтобы закрыть слепое пятно.

В основном:

   Set the edge to detect the next interrupt event
   Clear the interrupt flag
   if (the event has already occurred)
   {
      Set the interrupt flag to force the interrupt
   }
   Enable the interrupt

Если время отклика на событие должно быть согласованным (например, 1 мс +/- 10 мкс после того, как после того, как входная линия повысится, передайте сигнал события), то прерывания обычно являются лучшими.

Если время ответа на событие должно быть в пределах определенного времени (например, в пределах 1 мс от входной линии, идущей вверх, передать сигнал события), тогда прерывание будет наилучшим.

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

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

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

Если событие не является критичным по времени и потенциально шумным (например, кто-то нажимает на переключатель), тогда опрос позволяет простую фильтрацию, не пропуская долгосрочные переходы. Распространенной ошибкой является многократный опрос при настройке:

void fnInitialiseSystem(void)
{
   if (MODE_INPUT == MODE_A) /*First polling of the MODE_INPUT*/
   {
      PR2 = PR2_MODE_A;
   }
   else
   {  
      PR2 = PR2_MODE_B;
   }
   OpenTimer2( TIMER_INT_ON &
               T2_PS_1_1     &
               T2_POST_1_8   );

   if (MODE_INPUT == MODE_A) /*Second polling of the MODE_INPUT*/
   {
      CurrentMode = MODE_A;
      PROBE_INT_EDGE = CLEAR_TO_BLOCKED;
   }
   else
   {  
      CurrentMode = MODE_B;
      PROBE_INT_EDGE = BLOCKED_TO_CLEAR;
   }
}

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

Например, при отключении переключателя просто проверяйте переключатель регулярно (каждые 1 мс?), И если количество из них (скажем, 16) отличается (переключатель закрыт) от отфильтрованной версии (переключатель открыт), обновите результат и выполните действие требуется. Будьте осторожны с наложением сигналов, колебательный сигнал может выглядеть стабильно!

Пример использования опроса и прерываний, опять же, для использования входа, который не часто меняется, но шумит при этом. Еще раз, коммутатор является хорошим примером этого: код может установить прерывание для проверки изменения состояния переключателя, когда происходит прерывание, тогда переключатель можно регулярно опрашивать до тех пор, пока состояние переключателя не станет «стабильным» (либо измененным, либо состояние или возврат к тому, что было). Это дает преимущество в виде низких издержек обработки, когда ничего не происходит, и фильтрации шума, когда что-то происходит.

7 голосов
/ 19 июня 2010

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

4 голосов
/ 27 июня 2010
3 голосов
/ 24 июня 2010

Существует множество конструктивных ограничений, которые могут повлиять на принятие решения.Мое приложение имеет комбинацию прерываний и опросов:

  • Внешние и внутренние источники синхронизации запускают прерывания - очень важно точно пометить метки времени, чтобы мы могли синхронизировать их.
  • Входящие последовательные сообщения вызывают прерывания.Полученные FIFO должны быть обслужены до их переполнения.
  • Исходящие сообщения вызывают прерывания, когда FIFO частично пуст - его необходимо пополнить, прежде чем он опустошится.
  • Набор семафоров ISR, которые опрашиваются в фоновом режиме.Это имеет 2 преимущества:
    • Вычисления, необходимые для обработки входящих событий, могут быть длительными;если бы он был оставлен в ISR, он мог бы задержать другие ISR сверх срока их обслуживания.
    • События могут быть упорядочены.Например, цикл опроса может гарантировать, что вычисление X всегда происходит между сбором данных АЦП и анализом входящего сообщения, даже если иногда сообщение приходит немного раньше, чем ожидалось.
3 голосов
/ 21 июня 2010

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

Единственный раз, когда вы должны использовать опрос, это когда вы используете планировщик, а буферы на вашем оборудовании достаточно глубоки, чтобы не потерять данные.

3 голосов
/ 19 июня 2010

Прерывания предпочтительны, когда требуется низкая задержка. Если вы опрашиваете какое-либо условие N раз в секунду, то в среднем вы обнаружите это условие за половину от 1 / N после того, как оно действительно произошло.

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

3 голосов
/ 19 июня 2010

В основном, режим опроса используется в случае, если режим прерывания недоступен по некоторым аппаратным или программным причинам.Таким образом, режим прерывания является более предпочтительным с точки зрения энергопотребления, производительности и т. Д. (Согласен с Полом Р.).Режим опроса также может использоваться при создании прототипов для ядер без периферийных устройств и для некоторых целей тестирования.

3 голосов
/ 19 июня 2010

короткий ответ - использовать метод прерывания, когда опрос выполняется слишком медленно.(слишком медленно, я имею в виду, если при опросе теряются данные, необходим метод прерывания)

...