Рэймонд Чен отвечает на известную шутку:
— Папа, покажи, какая винда многозадачная!
— Сейчас, сынок, только дискету доформатирую...
Кто же целыми днями форматирует дискеты? Оказывается, многие гики только этим и заняты. (Вообще-то, можно покупать дискеты уже отформатированными, только тссс!) Но почему Windows 95 подвисала при форматировании дискеты?
Всё дело в совместимости с MS-DOS.
Как мы видели немного раньше, MS-DOS в Windows 95 выступала как слой для старых 16-битных драйверов. Несмотря на то, что в итоге операции ввода-вывода обрабатывались 32-битной файловой подсистемой, все они проходили через 16-битный код, чтобы 16-битные драйверы, TSR и подобные обработчики видели «нормальные 16-битные операции» и работали в привычном им окружении.
В 16-битном мире форматированием занималось программное прерывание 13h, и многие программы использовали этот факт, перехватывая прерывание так, чтобы получать управление при форматировании дискеты. Так делали некоторые TSR, программы для бэкапов (программы для бэкапов, разработанные для Windows 3.0, включали в себя 32-битные драйверы под Windows 3.x, называемые VxD, для отслеживания операций с дискетами). Но это объясняет не всё. В конце концов, Windows 95 прогоняла весь дисковый ввод-вывод, а не только форматирование дискет, через 16-битный код. Почему же форматирование дискет так существенно влияло на систему?
Как я отметил в статье по ссылке выше, 32-битная файловая подсистема тщательно подделывала свидетельства, заставляя 16-битный код верить в то, что за всё ответственна MS-DOS, хотя это и было неправдой. Любой, кто занимался программированием TSR (ого, определение любой, кто занимался программированием TSR когда-то охватывало массу людей, а сегодня описывает несколько десятков бывалых программистов, большинство из которых хотели бы забыть это как страшный сон), знает всё про флаг INDOS. MS-DOS устанавливала этот флаг на время обработки запроса ввода-вывода. Поскольку MS-DOS не допускала вложенного вызова самой себя, TSR должны были тщательно отслеживать этот флаг, чтобы знать, безопасно ли обращаться к MS-DOS. Флаг INDOS был 16-битным отражением сущности, которую 32-битное ядро называло Главной Критической Секцией; 32-битное ядро держало главную критическую секцию и флаг INDOS в одинаковом состоянии, чтобы не вызывать один и тот же драйвер MS-DOS или TSR параллельно несколько раз. Когда одна виртуальная машина захватывала главную критическую секцию, любая другая виртуальная машина, попытавшаяся сделать то же самое, была вынуждена ждать, пока первая виртуальная машина не отпустит секцию. Таким образом, параллельные вызовы драйвера или TSR блокировались.
Как я уже отметил, в 16-битном мире собственно форматированием занималась ROM BIOS, и в целях совместимости форматирование дискет по-прежнему посылалось через 16-битное программное прерывание 13h, чтобы все TSR и драйверы могли увидеть происходящее. Многие BIOSы безумны, так что при запросе на форматирование дискеты 32-битное ядро проделывало большую дополнительную работу, чтобы BIOS получала именно то окружение, которого хотела. В частности, порты аппаратного таймера переходили от менеджера виртуальных машин под полный контроль BIOS, чтобы не влиять на работу циклов, используемых BIOS для задержек при форматировании, для которых критично время выполнения.
Итак, посчитаем итоговый урон. Пока дискета форматируется, таймер развиртуализован для точности циклов, используемых BIOS для задержек. Только виртуальная машина, форматирующая дискету, получает сигналы от таймера; остальным приходится ждать. Отсутствие сигналов таймера означает, что никто не вызывает планировщик с сообщением «пора дать поработать другому потоку». Далее, главная критическая секция заблокирована на время операции, что означает, что никакой другой поток не может начинать операции ввода-вывода. Всё это ещё усугубляется тем, что дискета — медленное устройство, и любая операция, ожидающая окончания работы с дискетой, вынуждена остановиться и подождать несколько секунд.
Хорошо хоть, что дискеты форматируются по дорожке за раз, и система блокируется не на всё время форматирования. BIOS подаётся команда отформатировать одну дорожку, и по окончании процесса таймер возвращается в нормальное состояние (что позволяет планировщику заняться своим делом), главная критическая секция разблокируется (и ожидающие операции ввода-вывода получают шанс на выполнение). Но потом возвращается программа FORMAT.COM и форматирует следующую дорожку, и система возвращается назад в состояние подождём, не будем отвлекать BIOS от работы.
Аналогично случаю 32-битной файловой подсистемы, существовал 32-битный драйвер дискет, пытавшийся перехватить операции форматирования в самом конце. Если это получалось, драйвер делал работу по форматированию одной дорожки вместо BIOS. Доблестная попытка, но сколь бы высокопроизводительным ни был драйвер, это не имеет значения; скорость форматирования дорожки ограничена в основном механикой дискеты.
Конечно, если бы Windows 95 не должна была поддерживать совместимость с 16-битными драйверами, TSR и сомнительными BIOS, она могла бы направлять запросы форматирования прямо в 32-битный драйвер дискет, не отвлекаясь на абсурдные операции с таймером и главной критической секцией. Но вообще-то у нас уже была система, отказавшаяся от совместимости с 16-битными драйверами, TSR, 16-битными Windows-программами с собственными 32-битными VxD-драйверами и сомнительными BIOS. Она называлась Windows NT.
Если вы хотели Windows NT, вы знали, где её найти.
Автор: grechnik