[Previous] [Next]

Сигналы прерываний

Как правило, устройства функционируют параллельно и асинхронно относительно действий центрального процессора. Поэтому, для ситуаций, когда им требуется внимание со стороны драйвера, код которого выполняется на центральном процессоре, была выработана тактика использования прерываний, когда устройства сигнализируют о необходимости обслуживания, то есть генерируют прерывания. Разные процессоры реализуют разные способы, как "привлечь" их, процессорное, внимание. Но имеется и общее место в эти способах: всегда задействован один (или несколько) из выводов процессора (или вспомогательной микросхемы). За этот вывод устройство может "подергать", когда потребуется участие процессора.

В обязанности процессора, если он намерен перейти к обслуживанию по поступившему сигналу, входит сохранение состояния процессора, контекста выполняемого программного потока. Лишь после этого процессор(будет правильнее сказать — операционная система) может выполнить переход к программному коду Процедуры Обслуживания Прерывания (Interrupt Service Routine, ISR), которую регистрирует драйвер, взявший на себя работу по представлению данного устройства в операционной системе.

Обычно устройства генерируют сигналы прерываний в ситуациях:

Устройства, которые не способны генерировать прерывания, могут создать ситуацию серьезной деградации операционной системы. В связи с тем, что огромное количество выполняющихся потоков использует центральный процессор совместно, недопустимо позволять какому-либо драйверу такую роскошь, как ожидание полного завершения "его" текущей операции. При работе с подобными устройствами, не умеющими "разговаривать прерываниями", можно применять тактику опроса через определенные промежутки времени. В англоязычной литературе такой метод называется 'polling'.

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

Приоритеты прерываний

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

Для чего приоритет прерывания нужен? В момент, когда процессор занят выполнением программного кода в ответ на прерывание от низкоприоритетного устройства (например, выполняет его ISR-процедуру обработки прерываний), вполне может поступить сигнал прерывания от устройства с высоким приоритетом. В данном случае, центральный процессор получит два прерывания — второе над первым — и перейдет к обработке того, которое имеет больший приоритет, сохраняя, разумеется, контекст отложенного "в сторону" потока. И наоборот, обработка прерывания низкого уровня, поступившего при обслуживании высокоприоритетного, задерживается до момента, пока высокоприоритетное не будет обработано полностью и объявлено завершенным.

Важно отметить, что в режиме ядра программный поток какого-либо приоритета не может быть прерван ради выполнения кода потока даже равного с ним приоритета — в отличие от пользовательского режима, когда даже самые низкоприоритетные потоки когда-нибудь получают возможность поработать. Этим, в частности и объясняются многочисленные и "назойливые" рекомендации в литературе по программированию драйверов не задерживаться в коде процедур обработки прерываний (с высоким приоритетом), поскольку игнорирование этого правила может приводить к быстрой и необратимой деградации системы. Это требование становится особенно очевидным, если воспользоваться системным программным обеспечением, дающим информацию о количестве прерываний в секунду — оно меняется от полусотни до тысячи. Разумеется, если разработчик драйверов не будет придерживаться правила "меньше работай на уровнях DIRQL", то система не сможет нормально работать, а драйвер никогда не получит цифровую подпись Microsoft.

Векторы прерывания

Некоторые устройства и некоторые процессорные архитектуры допускают механизм автоматической диспетчеризации — переходов "по вектору", то есть адресу программных процедур, при поступлении сигналов о прерываниях. При другом методе векторизация не применяется, и для всех типов прерываний обслуживание предоставляется обобщенной процедурой. Такая процедура просматривает в порядке приоритетности весь список устройств, которые могли бы вызвать прерывание, и определяет, какое устройство требует обслуживания на самом деле. Очевидно, что в современных компьютерных системах, где генерируется от нескольких десятков до нескольких тысяч прерываний в секунду, существенно более эффективным оказывается векторный подход.

Передача сигналов прерываний

При генерации прерываний используются две основные стратегии. Более старый и менее предпочтительный механизм носит название edge-triggered (управляемые перепадом, управляемые фронтом) или latched прерывания. Устройства, которые генерируют такие прерывания, сигнализируют о потребности в обслуживании осуществлением перехода на физически существующем проводе (например, на одном из проводников шины или соединительного кабеля) из одного логического состояния в другое, скажем, из 1 в 0. Как только этот переходной процесс прошел, устройство может отпустить линию (отпустить прерывание), восстановив параметры электрического сигнала, в данном случае, обозначающие логическую 1. Другими словами, линия прерывания такого устройства "пульсирует" под его руководством, а процессор должен обратить внимание на проходящие импульсы.

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

Классическим примером оборудования, где случаются потери такого типа прерываний, являются последовательные СОМ порты. По традиции, COM1 и COM3 используют одно определяемое по фронту прерывание, а именно IRQ4. В результате, невозможно одновременно подключить к этим двум портам оборудование, которое использует управляемое прерываниями программное обеспечение. Попытки включить мышь в COM1 и модем в COM3 рано или поздно, но — неминуемо приводят к остановке одного из драйверов, который ожидает "пропавший" сигнал о прерывании.

Эти ограничения преодолеваются реализацией второго механизма, известного как level-sensitive, чувствительный к уровню, или level-triggered, управляемый уровнем. Устройства удерживают общую аппаратную линию (совместно используемый проводник) в соответствующем состоянии до тех пор, пока потребность каждого не будет удовлетворена. Теперь для процессора нет проблем в том, чтобы зарегистрировать оба прерывания, так как линия удерживается в этом состоянии до момента завершения обслуживания и первого, и второго устройства — это позволяют делать специальные типы цифровых схем. В случае если два прерывания происходят одновременно, обслуживается устройство с более высоким приоритетом, а после и другое устройство, поскольку оно продолжает сигнализировать, удерживая линию в соответствующем состоянии и после окончания обработки запроса первого, высокоприоритетного, устройства.

Сродство к процессору

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

Как правило, существуют некоторые компоненты аппаратного обеспечения, которые позволяют драйверу конфигурировать и распределять сигнал прерывания. Если отдельный процессор обслуживает прерывания, поступающие только от определенного устройства, то про такие прерывания говорят, что они имеют "сродство к процессору" (processor affinity). Назначение конкретного процессора для обработки конкретного прерывания может быть использовано для контроля сбалансированности загрузки отдельного устройства, если в системе присутствуют несколько процессоров и несколько управляемых устройств.

Механизмы передачи данных

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

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

Программируемый ввод/вывод

Устройства, использующие программируемый ввод/вывод (Programmed I/O, PIO), осуществляют передачу данных непосредственно через регистры устройства. Драйвер должен использовать инструкцию ввода/вывода (I/O instruction) для чтения из регистра или записи в регистр устройства каждого байта данных. При больших объемах драйвер должен поддерживать адресацию буферной области и счетчик переданных данных.

Поскольку реальная скорость передачи данных таких устройств много меньше, чем возможности процессора по чтению или записи в регистры данных, то устройства с таким подходом обычно генерирует прерывание для каждого байта (слова) передаваемых данных. Последовательный СОМ порт является одним из примеров PIO устройств. Более совершенные устройства используют накопительные FIFO, что позволяет им в одно прерывание передавать 4 или 16 байт данных. И все же количество прерываний относительно переданного объема данных весьма велико, отчего этот метод пригоден лишь для медленных устройств.

Прямой доступ к памяти

Прямой доступ к памяти (Direct Memory Access, DMA) использует выгоды от вовлечения в работу вторичного процессора, называемого контроллером DMA (DMA controller, DMAC, контроллер ПДП). Этот контроллер является вспомогательным процессором с ограниченным набором возможностей и обязанностей, но при этом с достаточным интеллектом и статусом, чтобы выполнять передачу данных между устройством и оперативной памятью. Контроллер DMA работает параллельно с основным процессором (процессорами), и обычно его деятельность почти незаметна в общем функционировании системы.

При инициации операции ввода/вывода с привлечением DMA метода драйвер должен выполнить установку нужного состояния DMA контроллера (запрограммировать его), определив адрес начала буферной области и количество передаваемых данных. По поступлению от драйвера указания начать работу DMA контроллер приступает к выполнению передачи данных между устройством и системной оперативной памятью. Когда DMA контроллер завершает передачу данных полностью, генерируется прерывание. Таким образом, драйверный код выполняется только в начале операции передачи данных и затем — лишь по ее завершении, освобождая центральный процессор для выполнения других задач.

Следует обратить особое внимание на то, что в Windows NT при DMA операциях всегда используются логические адреса (трюк с памятью, схожий с виртуальной адресацией, но предназначенный специально для DMA операций), позволяющие "обмануть" DMA контроллер, для которого логические адреса кажутся непрерывными, хотя и могут представлять физически разрывные области памяти.

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

Необходимо отметить, что реальная DMA передача данных не является очевидно и безусловно выгодной. Вторичный процессор, каковым является DMAC, конкурирует с центральным процессором в использовании пропускной способности системной оперативной памяти и шин. В случае если центральный процессор обращается к системной памяти часто, то кто-то из них — либо центральный процессор, либо DMAC — вынуждены ждать, пока предыдущий цикл обращения к памяти не закончится. Можно лишь надеяться, что при больших размерах кэш-памяти современных процессоров, у последнего нечасто возникает крайняя необходимость использовании максимальной пропускной способности памяти. Но все же, система с большим количеством устройств, реализующих bus master DMA (одна из разновидностей операций прямого доступа к памяти), может обнаружить, что возможности одновременного доступа к памяти исчерпаны. Ниже рассмотрены два основных типа DMA операций.

DMA операции с использованием системных контроллеров

Первоначальная спецификация персонального компьютера по IBM (и последовавшие стандарты) включали основную плату (называемую ныне "материнской") с набором общих DMA котроллеров. Каждый DMA контроллер предоставляет DMA каналы (DMA channel), и данное устройство может быть сконфигурировано так, чтобы использовать один (или более) доступных каналов. Изначально существовало четыре канала, которые были расширены до семи при введении спецификации AT. Системный DMA (system DMA) известен еще как slave DMA.

Преимущество использования системного DMA состоит в том, что количество аппаратной логики для реализации DMA в устройстве уменьшается. К минусам следует отнести то, что в случае совместного использования канала данным устройством, оно получает возможность участия в DMA передаче данных только один раз за определённый временной интервал. В каждый конкретный момент времени DMA канал находится "в собственности" только одного устройства, остальные попытки использования этого канала со стороны других устройств откладываются до момента, когда первое устройство "откажется" от собственности на канал. Такое совместное использование канала дает плохие результаты при использовании его для двух высокоскоростных устройств. Контроллер флоппи дисководов в большинстве персональных компьютеров как раз является устройством, реализующим операции slave DMA.

Операции bus master DMA

Более сложные устройства, которые не желают быть зависимыми от системных DMA контроллеров, содержат собственные аппаратные средства обеспечения DMA. Так как эти средства принадлежат собственно устройству, то передача происходит по "воле" устройства — если, разумеется, протокол шины поддерживает такие действия. Для выполнения своей операции устройству необходимо получить "контроль над шиной" в результате процедуры, которая описывается в протоколах соответствующих шин.

Память, отведенная устройству

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

Рис. 5.1
Доступ к памяти, имеющейся в устройстве

В некоторых случаях эти диапазоны определены жестко, как в случае с диапазоном адресов 0x0A0000-0x0AFFFF буфера адаптера VGA.

Память, отведенная устройству, является ресурсом, предоставляемым драйверу устройства операционной системой, и обычно с ним можно ознакомиться в апплете свойств драйвера в настройках системы (Пуск - Настройка - Панель Управления - Система - Устройства - Диспетчер Устройств - устройство - ресурсы).

Ресурсы, используемые устройством

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

В случае PnP устройств, идентификаторы производителя и типа устройства являются критерием выбора драйвера при загрузке системы или же при подключении устройства (если оно было подключено после загрузки).

Для обеспечения автоматической конфигурируемости, устройство должно разрешать авторизованному программному обеспечению динамически устанавливать и изменять установки порта ввода/вывода, прерывания и канала DMA, которые будут использованы при работе с данным устройством. Это позволит операционной системе разрешить конфликты ресурсов среди конкурирующих устройств.