Пути расширения реального времени для NT
Появление расширений реального времени для Windows NT явилось попыткой применить для создания приложений реального времени господствующую программную технологию, которая имеет огромный набор прикладных программ под Windows, мощный программный интерфейс WIN32, большое количество специалистов, знающих эту систему. Несмотря на то, что Windows NT создавалась как сетевая ОС, в нее при создании были заложены элементы реального времени, а именно – двухуровневая система обработки прерываний (ISR и DPC), классы реального времени (процессы с приоритетами 16-32 планируются в соответствии с правилами реального времени).
Windows NT не годится для построения систем жесткого реального времени (система непредсказуема – время выполнения системных вызовов и время реакции на прерывания сильно зависит от загрузки системы; система велика; нет механизмов защиты от зависаний и т.д.). В системах мягкого реального времени Windows NT используется только при выполнении целого ряда рекомендаций и ограничений.
Разработчики расширений, попытаясь исправить эти недостатки, пошли двумя путями:
1) Использовали ядра классических ОС РВ в качестве дополнения к ядру Windows NT. Таковы решения фирм "LP Eleknroniks" и "Radisys". В первом случае параллельно с Windows NT работает ОС VxWorks, во-втором случае – InTime. Кроме того, предоставляется набор функций для связи приложений реального времени и приложений Windows NT. Так у LP Elektroniks: вначале стандартным образом загружается Windows NT, затем с помощью специального загрузчика загружается ОС VxWorks, распределяя под себя необходимую память Windows (что в дальнейшем позволяет избежать конфликтов памяти между двумя ОС). После этого ОС VxWorks отдает процессор ядру Windows NT только в случаях, когда в нем нет надобности для приложений VxWorks. В качестве канала для синхронизации и обмена данными между Windows NT и VxWorks служат псевдодрайверы TCP/IP в обоих системах. Технология использования двух систем на одном компьютере понятна – работу с объектом выполняет приложение реального времени, передавая затем результаты приложениям Windows NT для обработки, передачи в сеть, архивирования и пр.
Рис. 2.5. Упрощенная архитектура NT |
2) Вариант расширений реального времени фирмы VenturCom выглядит иначе: здесь сделана попытка "интегрировать" реальное время в Windows NT путем исследования причин задержек и зависаний и устранения этих причин с помощью подсистемы реального времени. Решения фирмы "VenturCom" (RTX 4.2) базируются на модификациях уровня аппаратных абстракций Windows NT (HAL – Hardware Abstraction Layer) – программного слоя, через который драйверы взаимодействуют с аппаратурой. Модифицированый HAL и дополнительные функции (RTAPI) отвечают за стабильность и надежность системы, обеспечивая отслеживание зависания приложений Windows NT или блокировку прерываний. В состав RTX входит также подсистема реального времени RTSS, с помощью которой Windows NT расширяется дополнительным набором объектов. Среди новых объектов – нити (потоки, процессы) реального времени, которые управляются специальным планировщиком реального времени (256 фиксированных приоритетов, алгоритм – приоритетный с вытеснением). Побочным результатом RTX является возможность простого создания програм управления устройствами, т.к. среди функций RTAPI есть и функции работы с портами ввода/вывода и физической памятью. Предложения VenturCom характерны еще и тем, что они предоставляют возможность конфигурирования Windows NT и создания встроенных конфигураций (без дисков, клавиатурны и монитора) (Интегратор Компонентов – CI).
На рис. 2.5 приведена упрощенная структура Windows NT.
Ядро Windows NT и драйверы. Единственной модифицируемой частью ядра являются драйверы устройств. Все расширения реального времени построены на модификациях уровня аппаратных абстракций и создании специфических драйверов.
Модификации уровня аппаратных абстракций. Уровень аппаратных абстракций HAL – нижний уровень программного обеспечения, "скрывающий" от исполнительной системы NT аппаратно-зависимые детали, такие, как контроллеры ввода/вывода и контроллер прерываний. Первый вход в обслуживание прерываний происходит именно на HAL-уровне. Следуя объектно-ориентированной модели, все компоненты ОС взаимодействуют, посылая сообщения друг другу. Вызовы к системным сервисам реализованы посредством сообщений, которые посылаются из процесса в пользовательском режиме в сервис ядра ОС. Это позволяет каждой части ОС разрабатываться независимо и увеличивает общую надежность проекта. Приложения не имеют доступ к аппаратуре, а управление осуществляется сервисами, запущенными на уровне ядра. Это позволяет переносить NT на другие аппаратные платформы. Решения, основанные на данном подходе, были предложены фирмой VenturCom. Структура расширений Windows NT этого типа приведена на рис. 2.6.
Рис. 2.6. Структура расширений NT в версии VenturCom |
Так как аппаратные прерывания попадают вначале в HAL и только затем передаются ядру, логично использовать прерывания от таймера для создания на базе модификаций HAL дополнительного диспетчера, а именно, диспетчера нитей реального времени. В итоге получаются два набора приложений: стандартные приложения NT и приложения реального времени, управляемые HAL-диспетчером, и два класса задач, которые исполняются на одном процессоре, но никак не связаны между собой. Приложения реального времени не имеет доступа к набору сервисов Windows NT (графический интерфейс, сети и т.д.). Поэтому разработчики, выбравшие такой вариант реализации, должны сами обеспечить интерфейс между приложениями реального времени и стандартными приложениями NT. Специалисты VenturCom предлагали решить эту проблему на двух уровнях. С одной стороны, существует механизм взаимодействия приложений реального времени с приложениями NT через разделяемую память (на рис. 2.6 этот механизм показан стрелкой IPC – Inter Process Communication), а с другой стороны, специфический драйвер NT позволяет стандартным приложеням "увидеть" подсистему реального времени как устройство (на рис. 2.6 этот механизм показан стрелкой DD_Com – Device Driver Communication).
Дополнение стандартного ядра NT ядром реального времени. Этот подход лежит в основе предложений фирм Radisys, Imagination и LP Elektronik. Имеются две разные его реализации:
· разместить ядро реального времени внутри программы обслуживания прерываний Windows NT или в драйвере устройства;
· разместить ядро реального времени вне адресного пространства Windows NT.
Реализация первой идеи была предложена компанией LP Elektronik. На шину ISA ставится дополнительная плата (LP-Realtime Accelerator), снабженная таймером и имеющая возможность управлять большинством линий прерываний ISA. LP Elektronik предлагает технологию написания программ обработки прерываний (ISR) от этой платы. Эта технология позволяет расширить программу обработки прерываний до размеров полноценного ядра ОС РВ.
LP Elektronik не предлагает собственных расширений реального времени для Windows NT, однако на базе ее технологии в NT было внедрено ядро ОС РВ VxWorks. Для взаимодействия между процессами VxWorks и Windows используют "псевдо-сеть" ТСР/IP. Для этого пришлось разработать всего лишь два драйвера TCP/IP – один для Windows и один для VxWorks.
Рис. 2.7.Структура расширений NT c дополнительными ядрами реального времени |
Фирма Radisys осуществила второй подход в продукте INtime, основанный на ядре реального времени ОС iRMX, обеспечивающий модификацию уровня HAL и разработку специфического драйвера. Radisys разработала механизм внедрения одной ОС в другую, который управляет одновременным исполнением и целостностью ядер Windows NT и реального времени, осуществляет защиту памяти и разделяет адресные пространства процессов. Процессы и прерывания реального времени имеют приоритет по сравнению с процессами и прерываниями Windows NT. Структура расширений Windows NT c дополнительными ядрами реального времени приведена на рис. 2.7.
Ядро NT управляет процессором, планируя потоки и направляя их на выполнение, реагирует на прерывания и исключения и реализует низкоуровневые механизмы синхронизации, которые используются им самим и исполнительной системой. Другие модули исполнительной системы NT полагаются на функции и примитивы, предоставляемые ядром; "поверх них" строится системная стратегия и обеспечиваются различные возможности пользовательского режима.
Примитивы ядра включают группы объектов, инкапсулируемые в объектах исполнительной системы. Управляющие объекты ядра обеспечивают реализацию разнообразных функций ОС, тогда как диспетчерские объекты ядра – это примитивы с встроенными синхронизационными возможностями. Синхронизация, как внутри ядра, так и за его пределами, критична для корректного функционирования ОС. Она особенно сложна на многопроцессорных компьютерах. Ядро синхронизирует свое собственное выполнение для правильного функционирования, а предоставляемые им механизмы позволяют делать то же самое остальным частям исполнительной системы.
Ядро для системы ввода/вывода предоставляет объекты и функции, используемые драйверами устройств для синхронизации работы в многопроцессорной среде и для восстановления операций ввода/вывода при аварии питания.
ОС состоит из расположенных друг над другом уровней кода. Верхние уровни используют более примитивные (но в данном случае более мощные) функции и структуры данных нижних уровней. Ядро выполняет основные функции Windows NT, определяя, как ОС использует процессор или процессоры и обеспечивая рациональность их использования. Главной задачей при создании ядра NT было обеспечение базы, состоящей из примитивов и механизмов с тщательно определенным и предсказуемым поведением при выполнении задач высокоуровневыми компонентами исполнительной системы NT. Используя примитивы ядра, исполнительная система NT создает бесконечное разнообразие абстракций высокого уровня. Ядро отделяет себя от остальных частей исполнительной системы, реализуя механизмы ОС и избегая установления жестких правил.
Отделение механизмов ОС от ее правил является важным принципом Windows NT. Механизмы – это способы выполнения различных задач в системе, и выражением их являются алгоритмы и код. Правила или стратегии определяют, когда и какие задачи должны быть выполнены и следует выполнять некоторые из них. Код ОС, поддерживающий разделение между механизмами и стратегией, помогает системе оставаться гибкой. Со временем правила могут меняться, не вызывая множества изменений в системе или механизмах.
Принцип разделения механизмов и стратегий используется в Windows NT на нескольких уровнях. На самом высоком уровне каждая подсистема среды устанавливает слой правил ОС, отличающийся от устанавливаемого другими подсистемами. Непосредственно под ними исполнительная система NT определяет другой, более фундаментальный слой правил, подходящий для всех подсистем. На нижнем уровне ОС ядро не устанавливает правил вообще и служит прослойкой между остальными частями ОС и процессором. Все операции, связанные с процессором, проходят через ядро, что обеспечивает большую переносимость и предсказуемость. Исполнительная система имеет лишь ограниченное влияние на выполнение этих операций (посредством вызова функций ядра).
Помимо функций, предоставляемых исполнительной системой NT, ядро решает четыре основных задачи:
· планирует выполнение потоков;
· передает управление процедурам обработки при возникновении прерываний или исключений;
· выполняет низкоуровневую многопроцессорную синхронизацию;
· реализует процедуры восстановления системы при сбое питания.
Ядро отличается от других компонентов исполнительной системы несколькими аспектами. В отличие от других частей исполнительной системы, оно никогда не откачивается из памяти. Аналогично, оно никогда не вытесняется, хотя его работа может быть прервана для обработки прерывания, т.е. многозадачность исчезает, а ядро всегда работает в привилегированном режиме процессора. Оно сделано компактным и переносимым, насколько это позволяют производительность и различия процессорных архитектур. Ядро написано в основном на С, с использованием ассемблера только для тех задач, которые требуют максимально возможной скорости выполнения или сильно зависят от особенностей процессора.
За пределами ядра исполнительная система представляет потоки и другие, совместно используемые ресурсы в виде объектов. Эти объекты требуют некоторых накладных расходов, связанных с правилами. Для работы с объектами необходимы описатели, проверки прав доступа, квоты ресурсов и механизмы выделения и освобождения памяти. Ядро избегает этих накладных расходов, поскольку реализует набор более простых объектов, называемых объектами ядра (kernel objects). Они помогают ядру управлять центральным процессором и поддерживают создание объектов исполнительной системы. Большинство объектов уровня исполнительной системы включают в себя один или несколько объектов ядра, объединяя их мощные атрибуты (определяемые ядром).
Группа объектов ядра управляющих объектами (control objects), устанавливает семантику управления функциями ОС. В эту группу входят объект-процесс ядра, объект – асинхронный вызов процедуры (asynchronous procedure call, APC), объект – отложенный вызов процедуры (deferred procedure call, DPC) и несколько объектов, используемых системой ввода/вывода. Другая группа объектов ядра – диспетчерские объекты (dispatcher objects) – включает средства синхронизации и изменяет или влияет на планирование потоков. Это поток ядра, мьютекс ядра, мутант ядра, событие ядра, пара событий ядра, семафор ядра и таймер ядра. Исполнительная система использует функции ядра для создания экземпляров его объектов, работы с ними и для создания объектов, которые она предоставляет процессам пользовательского режима.
Планирование потоков. Поток выполняется в адресном пространстве процесса и использует его ресурсы. Одной из функций ядра NT является отслеживание готовых к исполнению потоков и определение порядка их выполнения, т.е. задача, планирования потоков (thread scheduling). При выполнении необходимых условий ядро выбирает поток для исполнения и переключает контекст на него. Переключение контекста (context switch) – это процедура сохранения текущего машинного состояния, связанного с исполняющимся потоком, загрузка состояния другого потока и его запуск. Модулем, выполняющим эти обязанности, служит диспетчер ядра.
Объекты процесс ядра и поток ядра. Диспетчер следит за тем, чтобы из всех ожидающих исполнения потоков процессоры всегда исполняли именно те, которые необходимо исполнять в данный момент. Когда в системе происходит событие, изменяющее состояние потока, диспетчер просматривает список ожидающих потоков и переключает контекст на новый поток. Ядро работает с сокращенной версией объекта-потока, называемой объект-поток ядра (kernel thread object). Объект-поток ядра содержится внутри объекта-потока исполнительной системы и содержит информацию, необходимую ядру для направления потока на исполнение. Ядро реализует минимальную версию объекта-процесса, называемую объект-процесс ядра (kernel process object). На рис. 2.8 показано соотношение между объектами процесс ядра и поток ядра и их высокоуровневыми аналогами в исполнительной системе.
Рис. 2.8. Объект-процесс ядра и объекты-потоки ядра |
Рис. 2.9. Объект-процесс ядра |
Объект-процесс ядра содержит указатель на список потоков ядра (рис. 2.9). В объекте – процессе ядра находится указатель на каталог таблиц страниц процесса (используется для отслеживания виртуального адресного пространства процесса), общее время выполнения всех потоков процесса, базовый диспетчерский приоритет процесса по умолчанию и набор по умолчанию процессоров, на которых могут исполняться потоки процесса, – процессорное сродство (processor affinity). Управление информацией, хранящейся в объекте процесс ядра, осуществляет исключительно ядро. Другие части исполнительной системы считывают или изменяют ее, только вызывая функции ядра.
Объект-поток ядра сложнее, чем объект-процесс ядра. Он содержит информацию о процессорном сродстве потока (неполное подмножество сродства процесса) и общее время выполнения потока. В него входят базовый приоритет потока (который может отличаться от базового приоритета по умолчанию для процесса) и его текущий приоритет. Важный элемент данных, хранящихся в объекте-потоке ядра, – это диспетчерское состояние потока. В любой момент времени поток находится в одном из шести состояний; из них только одно делает его кандидатом на выполнение. Диспетчерские состояния потока показаны на рис. 2.10.
Рис. 2.10. Состояния потока |
"Жизненный цикл" потока начинается тогда, когда программа создает новый поток. Этот запрос спускается вниз к исполнительной системе NT, где диспетчер процессов выделяет пространство для объекта-потока и вызывает ядро для инициализации объекта-потока ядра, содержащегося внутри данного объекта. После инициализации поток проходит через состояния:
· Готовый. Когда диспетчер ищет поток для выполнения, он рассматривает совокупность потоков, находящихся в этом состоянии. Готовые потоки ждут своего выполнения.
· Резервный. При выполнении определенных условий диспетчер выполняет переключение контекста на этот поток. Для процессора системы в резервном состоянии может быть только один поток.
· Исполняющиеся. Если диспетчер переключает контекст на поток, последний переходит в это состояние и выполняется. Выполнение потока продолжается до тех пор, пока он не будет вытеснен ядром для выполнения более высокоприоритетного потока, не истечет его квант времени, он не завершится или не перейдет в состояние ожидания.
· Ожидающий. Объекты исполнительной системы, поддерживающие синхронизацию, всегда находятся в одном из двух состояний: они либо свободны, либо заняты. Фактически именно ядро реализует семантику ожидания и сигнализации Windows NT. Каждый синхронизационный объект, видимый пользовательскому режиму, включает в себя один или несколько диспетчерских объектов ядра. Ядро отвечает за установку диспетчерских объектов в состояние "свободен" в соответствии с твердо определенными правилами; выполняя свою задачу, ядро освобождает потоки, ждущие эти объекты, изменяя их состояние с "ожидающий" на "готовый".
Поток может перейти в состояние ожидания несколькими способами. Он может добровольно ждать у объекта для синхронизации своего выполнения; ОС (например, система ввода/вывода) может ждать какого-либо события для него; подсистема среды может приказать потоку приостановиться. Когда ожидание потока заканчивается, он снова переводится в готовое состояние для продолжения выполнения.
· Переходный. Поток находится в переходном состоянии, если он готов к исполнению, но необходимые ему ресурсы недоступны.
· Завершившийся. Когда поток заканчивает свое исполнение, он переходит в завершившееся состояние. После своего завершения объект-поток может быть удален.
В Windows имеется специальные сервисы, которые позволяют ограничить доступ к разделяемым ресурсам, ведь без помощи ОС отдельный процесс или поток не может сам определить, имеет ли он единоличный доступ к ресурсу. ОС Windows содержит непрерывную операцию проверки и установки флага доступа к ресурсу. Флаги, используемые для обеспечения синхронизации и управления доступом к ресурсам, называются семафорами (semaphore). Интерфейс Win32 поддерживает четыре типа объектов синхронизации – все они так или иначе основаны на понятии семафора.
Первым типом объектов является собственно семафор, или классический (стандартный) семафор. Он позволяет ограниченному числу процессов и потоков обращаться к одному ресурсу. При этом доступ к ресурсу либо полностью ограничен (один и только один поток или процесс может обратиться к ресурсу в определенный период времени), либо одновременный доступ получает лишь малое количество потоков и процессов. Семафоры реализуются с помощью счетчика, значение которого уменьшается, когда задаче выделяется семафор, и увеличивается, когда задача освобождает семафор.
Вторым типом объектов синхронизации является исключающий семафор (Mutual Exclusion Locks, Mutex),предназначенный для полного ограничения доступа к ресурсу, чтобы в любой момент времени к ресурсу мог обратиться только один процесс или поток.
Третьим типом объектов синхронизации является событие, или объект события (event object). Он используется для оповещения процессам или потокам о том, что произошло некоторое событие и для блокирования доступа к ресурсу, пока какой-нибудь другой процесс или поток не заявит о том, что данный ресурс может быть использован.
При помощи объекта синхронизации четвертого типа запрещают выполнение определенных участков кода программы несколькими потоками одновременно. Данные участки объявляют как критический раздел (critical section). Когда в этот раздел входит один поток, другим потокам запрещается делать то же самое, пока первый поток не выйдет из него. Критические разделы, в отличие от других типов объектов синхронизации, применяются только для синхронизации потоков внутри одного процесса. Другие же типы объектов могут быть использованы для синхронизации потоков внутри процесса или для синхронизации процессов.
Семафор позволяет одному или нескольким потокам получать доступ к объекту. Допустимое число потоков, которым будет разрешен одновременный доступ, указывается во втором параметре. Если это значение равно единице, то семафор будет исключающим, т.е. только один поток или процесс сможет одновременно обращаться к ресурсу.
Различают:
двоичные (булевские) семафоры – это механизм взаимного исключения для защиты критичного разделяемого ресурса;
счетные семафоры – это механизм взаимного исключения для защиты ресурса, который может быть использован не более чем ограниченным фиксированным числом задач n.
Счетчик семафора указывает количество задач, которым предоставлен доступ к ресурсу. Если значение счетчика равно нулю, то последующий доступ к ресурсу запрещается до тех пор, пока одна из задач не освободит семафор. Начальное значение счетчика семафора указывается в первом параметре конструктора (это значение не должно быть отрицательным и не должно превышать значение второго параметра конструктора). Начальное значение задается равным единице, чтобы хотя бы один поток мог получить семафор. Третий параметр конструктора указывает на строку, содержащую имя объекта семафора. Поименованные семафоры становятся системными объектами и используются другими процессами. Когда два процесса вызывают семафоры с одинаковыми именами, обоим процессам будет предоставлен один и тот же семафор – это позволяет синхронизировать процессы. Вместо имени строки можно указать NULL – в этом случае семафор будет локализован внутри одного процесса. Последний параметр конструктора является указателем на набор атрибутов прав доступа, связанный с семафором. Если этот параметр равен NULL, то семафор наследует данный набор у вызвавшего его потока.
Все операции над семафорами выполняются как единое элементарное действие, т.е. после начала операции ни один процесс не получит доступа к семафору до окончания или блокирования операции. В начале работы семафор должен быть создан, в конце – уничтожен.
Использование критических секций и мьютексов во многом похоже на рассматриваемые выше действия с семафорами и объектами событие. Использование критических разделов позволяет более эффективно организовать работу с потоками. Критическую секцию используют только внутри одного процесса. Так как процессы не имеют доступа к данным друг друга, а ресурсы физических устройств управляются специальными задачами-серверами (драйверами), наиболее типична ситуация, когда гонки за доступ к глобальным переменным устраивают потоки, исполняемые в рамках одного программного модуля. Чтобы гарантировать, что критическая секция кода исполняется одним потоком, используют механизм взаимоисключающего доступа мьютексы.
Как и критические секции, мьютексы предназначены для синхронизации нитей при совместном использовании ими разделяемых ресурсов. В отличие от критической секции мьютекс «виден» из разных приложений и может использоваться для синхронизации процессов. Мьютекс представляет собой специальный объект ОС, которым может обладать только одна нить. Другая нить может его захватить после того, как первая от него откажется. Схема поведения процессов представлена на рис. 2.11.
Рис. 2.11. Схема поведения процессов |
Мьютекс как упрощенная версия семафора не способен считать, он может лишь управлять взаимным исключением доступа к совместно используемым ресурсам или кодам. Мьютекс состоит из пары: булевского семафора и идентификатора задачи – текущего владельца семафора. Как и мьютекс, критическая секция может принадлежать только одному потоку. В Windows механизм критических секций предоставляет более эффективный механизм, чем мьютексы. Критическая секция не является объектом ядра (в отличие от семафоров и мьютексов). Она содержит несколько флагов и объект ядра и для проверки, занята она или нет, не переходит в режим ядра, а лишь проверяются флаги. Если в этот момент ни один из потоков не владеет объектом, то поток становится владельцем критической секции и продолжает выполнение. Если секция уже захвачена другим потоком, то выполнение потока, вызвавшего процедуру, приостанавливается до ее освобождения.
В борьбе за ресурсы могут возникнуть следующие неприятности.
Смертельный захват (Deadlock). Обычно побочные эффекты этой ситуации называются более прозаично – “зацикливание” или “зависание”, а причина этого – задачи не поделили ресурсы.
Инверсия приоритетов (Priority inversion). Алгоритмы планирования задач (управление доступом к процессорному времени) должны находиться в соответствии с методами управления доступом к другим ресурсам, а все вместе – соответствовать критериям оптимального функционирования системы. Эффект инверсии приоритетов является следствием нарушения гармонии в этой области. Ситуация здесь похожа на смертельный захват.
Блокировка (Lockout). Процесс ожидает ресурс, который никогда не освободится.
Голодовка (Starvation). Процесс монополизировал процессор.
Приоритеты планирования. Для определения порядка выполнения потоков диспетчер ядра использует систему приоритетов, направляя на выполнение потоки с высоким приоритетом раньше потоков с низкими приоритетами. Ядро прекращает исполнение или вытесняет (preempts) поток, если готов к выполнению поток с высшим приоритетом. Первоначально приоритет потока устанавливается в соответствии с приоритетом процесса, в котором он был создан (когда подсистема среды создает процесс, она назначает ему базовый приоритет по умолчанию). Поток наследует базовый приоритет и изменяет его так, чтобы он стал больше или меньше. В результате получается приоритет планирования, с которым поток и начинает исполняться. Для планирования выполнения потоков ядро поддерживает база данных диспетчера (dispatcher database). В базе данных диспетчера отмечается, какие потоки ждут выполнения и какие потоки на каких процессорах выполняются. Важная структура данных в базе данных диспетчера является очередью готовности диспетчера (dispatcher ready queue). Очереди (рис. 2.12) содержат готовые потоки, ждущие направления на исполнение.
Как видно из рис. 2.12, исполнительная система NT поддерживает 32 уровня приоритетов; потоки делятся на два класса: реального времени и переменного приоритета. Потоки реального времени с приоритами от 16 до 31, – это высокоприоритетные потоки, используемые программами с критическим временем выполнения, которые требуют немедленной реакции процессора. Для выбора очередного кандидата на исполнение диспетчер начинает с очереди наивысшего приоритета и спускается вниз, пока не найдет поток. Все потоки реального времени выполняется прежде потоков переменного приоритета. Большинство потоков в системе с уровнями приоритета от 1 до 15 (приоритет 0 зарезервирован для системных целей) относятся к классу переменного приоритета (variable priority), так как диспетчер корректирует их приоритеты для оптимизации времени отклика системы. Windows NT является системой с вытесняющей многозадачностью, диспетчер прерывает поток, если он израсходовал свой квант времени. Если прерванный поток с переменным приоритетом, то диспетчер понижает его приоритет до его базового приоритета.
Рис. 2.12. Очередь готовности диспетчера |
С другой стороны, диспетчер повышает приоритет потока после освобождения последнего из состояния ожидания. Добавка к приоритету потока определяется кодом исполнительной системы, находящимся вне ядра, величина которой определяется тем, какого события ожидал поток. Имеется тенденция к установлению для интерактивных потоков высокого переменного приоритета, для потоков, выполняющих ввод-вывод – среднего и для вычислительных потоков – низкого. (Приоритет потока переменного приоритета не может быть повышен до уровня потоков реального времени.)
Процессорное средство потока влияет на порядок исполнения потоков. Ядро выбирает поток в зависимости от его приоритета и проверяет, на каких процессорах он исполняться. Если процессорное сродство потока не позволяет ему выполняться ни на одном из свободных процессоров, то будет выполняться следующий по приоритету поток.
Когда в системе ничего не происходит, ядро предоставляет для каждого процессора поток простоя, который всегда готов выполняться, поскольку диспетчер считает, что их приоритет ниже приоритета всех остальных потоков. Поток простоя (в цикле) проверяет, не появился ли в резервном состоянии другой поток, готовый к исполнению на данном процессоре. При обнаружении его поток простоя инициирует переключение контекста на него. Потоки простоя проверяют также наличие ожидающих выполнения отложенных вызовов процедуры (DPC).
Переключение контекста. Если истек квант времени потока, ядро вытесняет его и выполняет перепланировку загрузки процессора. Однако истечение кванта времени – не единственная причина начала планировки. Она начинается, когда исполнение текущего потока не может продолжаться или когда изменилось состояние некоторого потока и текущий поток не является самым высокоприоритетным. Условия, вызывающие перепланировку, перечислены ниже:
· поток становится готовым к выполнению;
· истек квант времени потока, поток завершился или вошел в состояние ожидания;
· диспетчер или исполнительная система изменили приоритет потока;
· исполнительная система или прикладная программа изменили процессорное средство выполняющегося потока.
Цель перепланировки – выбор потока, который будет выполняться следующим на некотором процессоре, и перевод его в резервное состояние. При этом диспетчер должен направить его на выполнение. Когда выполняющийся поток завершился или не может продолжать исполнение по другой причине, диспетчер выполняет переключение контекста на новый поток. Контекст потока и процедура переключения контекста зависят от архитектуры процессора. Переключение контекста требует сохранения и загрузки данных:
· счетчик команд;
· регистр состояния процессора;
· содержимое других регистров;
· указатели стеков пользователя и ядра;
· указатель на адресное пространство для выполнения потока.
Для переключения контекста ядро сохраняет эту информацию, помещая ее в стек режима ядра текущего потока и обновляя указатель стека. Ядро загружает контекст нового потока и, если это поток другого процесса, загружает адрес каталога таблиц страниц процесса, чтобы сделать доступным его адресное пространство. После выполнения ядром некоторой очистки, управление передается по адресу, указываемому загруженным счетчиком команд, и поток начинает выполняться.
Дата добавления: 2016-04-06; просмотров: 1293;