Разгон и торможение Windows NT



         

Переключение контекста - часть 2


При небольшом количестве потоков накладные расходы на их переключения довольно невелики и ими можно пренебречь, но по мере насыщения системы они стремительно растут! На что же расходуется процессорное время? Прежде всего на служебные нужны самого планировщика (анализ очереди, ротацию приоритетов и т. д.), затем на сохранение/восстановление контекста потоков и процессов. Посмотрим, как все это устроено изнутри?

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

Процессоры семейства x86 поддерживают аппаратный механизм управления контекстами, автоматически сохраняя/восстанавливая все регистры при переключении на другую задачу, но Windows не использует его, предпочитая обрабатывать каждый из регистров вручную. Какое-то время автор думал, что I486C-ядро, ничего не знающее о MMX/SSE регистрах современных процессоров, и не включающее их в контекст, будет выигрывать в скорости, однако параллельная работа двух и более мультимедийных приложений окажется невозможной. В действительности же оказалось, что за сохранение/восстановление регистров сопроцессора (если его можно так назвать) отвечают машинные команды FXSAVE/FXSTOR, обрабатывающие и MMX/SSE регистры тоже, но чтобы выяснить это пришлось перерыть все ядро – от HAL'а до исполнительной системы!

Переключение контекста осуществляется служебной функцией SwapContext, реализованной в ntoskrnl.exe. Это чисто внутренняя функция и ядро ее не экспортирует. Тем не менее она присутствует в символьных файлах (symbol file), бесплатно распространяемых фирмой Microsoft. Полный комплект занимает порядка 150 Мб и неподъемно тяжел для модемного скачивания. Ряд утилит, таких, например, как Symbol Retriever, от NuMega, позволяют выборочно скачивать необходимые символьные файлы вручную, значительно сокращая время перекачки, однако, по непонятным причинам они то работают, то нет (Microsoft блокирует доступ?), поэтому, необходимо уметь находить точку входа в SwapContext самостоятельно. Это легко. SwapContext единственная, кто может приводить к синему экрану смерти с надгробной надписью "ATTEMPTED_SWICH_FROM_DPC", которой соответствует BugCheck код B8h. Загрузив ntoskrnl.exe в ИДУ (или любой другой дизассемблер), перечислим все перекрестные ссылки, ведущие к функциям KeBugCheck и KeBugCheckEx. В какой-то из них мы найдем PUSH B8h/CALL KeBugCheck или что-то в этом роде. Она-то и будет функцией SwapContex. Прокручивая экран дизассемблера вверх, мы увидим вызов HalRequestSoftwareInterrupt, которая, собственно, и переключает контекст, а в многопроцессорной версии ядра еще и машинную команду FXSAVE, которая тут совсем ни к чему и которая отсутствует в монопроцессорной версии. К тому же многопроцессорные версии намного щепетильнее относятся к вопросам синхронизации и потому оказывается несколько менее производительными.




Содержание  Назад  Вперед