Pull to refresh

Какую роль играла MS-DOS в составе Windows 95?

Reading time 5 min
Views 59K
Original author: Raymond Chen
MS-DOS в составе Windows 95 использовалась для двух целей:
  • Она служила загрузчиком.
  • Она выступала в качестве слоя совместимости с 16-битными драйверами.
Когда Windows 95 стартовала, сначала загружалась специальная версия MS-DOS, именно она обрабатывала ваш файл CONFIG.SYS, запускала COMMAND.COM, который выполнял ваш AUTOEXEC.BAT и в конце концов выполнял WIN.COM, который в свою очередь начинал процесс загрузки 32-битного менеджера виртуальных машин VMM.

Эта специальная версия MS-DOS была полностью функциональна в той мере, в которой слова «полностью функциональна» вообще применимы к MS-DOS. По-другому и быть не могло, при выходе в режим эмуляции MS-DOS только эта версия и оставалась работать.

Программа WIN.COM начинала загрузку того, что большинство людей называют собственно «Windows». Посредством копии MS-DOS она загружала менеджер виртуальных машин, считывала файл SYSTEM.INI, загружала драйверы виртуальных устройств, затем выключала EMM386 (если таковой был) и переключалась в защищённый режим. «Настоящая Windows» с точки зрения большинства людей — именно защищённый режим.

В защищённом режиме драйверы виртуальных устройств творили свою магию. В числе их действий было вытаскивание всего состояния MS-DOS, перевод его в состояние 32-битной файловой подсистемы и отключение MS-DOS. Все дальнейшие файловые операции направлялись в 32-битную файловую подсистему. Когда программа обращалась к int 21h, ответственной за обработку оказывалась 32-битная файловая подсистема.

Здесь вступает в игру вторая роль MS-DOS. Видите ли, программы и драйверы MS-DOS любили встраиваться в глубины операционной системы. Они могли заменять обработчик прерывания 21h, они могли патчить код системы, они могли заменять низкоуровневые дисковые обработчики int 25h и int 26h. Они могли также творить умопомрачительные вещи с прерываниями BIOS типа int 13h, ответственного за работу с дисками.

Когда программа обращалась к int 21h, сначала запрос направлялся в 32-битную файловую подсистему, где проходил некоторую предобработку. Затем, если файловая подсистема обнаруживала, что кто-то перехватил вектор int 21h, она переходила назад в 16-битный код, чтобы позволить перехватчику выполниться. Замена вектора int 21h идеологически похожа на сабклассинг окна. Вы получаете старый вектор и устанавливаете новый вектор. Когда установленный вами обработчик вызывается, вы что-то делаете, а затем вызываете старый обработчик. После возврата из старого обработчика вы можете ещё что-нибудь сделать, прежде чем вернуть управление.

Одним из 16-битных драйверов, загружавшихся из CONFIG.SYS, был IFSMGR.SYS. Его задачей было перехватить MS-DOS первым, прежде чем все остальные драйверы и программы получат свой шанс! Этот драйвер был в сговоре с 32-битной файловой подсистемой, возвращаясь из 16-битного кода назад в 32-битный, чтобы файловая подсистема могла продолжить свою работу.

Другими словами, MS-DOS была всего лишь исключительно искусной подсадной уткой. 16-битные драйверы и программы патчили и перехватывали обработчики, которые для них выглядели совсем как настоящая MS-DOS, но в действительности были приманкой. Если 32-битная файловая подсистема видела, что кто-то купился на приманку, она заставляла подсадную утку крякать.

Начнём с системы без «злобных» драйверов и программ, внедрившихся в MS-DOS.


Это рай. 32-битная файловая подсистема оказалась способной проделать всю работу, не взаимодействуя с надоедливыми драйверами, творящими причудливые вещи. Обратите внимание на дополнительный шаг обновления переменных состояния MS-DOS. Хотя мы и извлекли их в ходе загрузки, мы поддерживаем их в актуальном состоянии, поскольку драйверы и программы часто «знали» о них, обходили операционную систему и работали непосредственно с переменными состояния. Следовательно, файловая подсистема должна была поддерживать иллюзию ответственности MS-DOS (несмотря на то, что на самом деле MS-DOS уже не работает), чтобы такие драйверы и программы видели то, что ожидали.

Обратите ещё внимание на то, что переменные состояния разные для разных виртуальных машин. (То есть каждый открытый сеанс MS-DOS получал свою собственную копию переменных состояния.) В конце концов, у каждого сеанса MS-DOS была отдельная текущая папка, отдельная таблица файлов и тому подобное. Впрочем, всё это было спектаклем, потому что настоящий список открытых файлов хранился в 32-битной файловой подсистеме. Иначе и быть не могло, поскольку дисковые кэши должны были быть согласованы, а ограничения совместного доступа к файлам должны были проверяться глобально. Если один сеанс MS-DOS открыл файл для монопольного доступа, то попытка программы, работающей в другом сеансе MS-DOS, открыть тот же файл должна была завершиться с ошибкой.

Хорошо, это был простой случай. Сложный случай: у вас был драйвер, перехвативший int 21h. Я не знаю, что этот драйвер делает, допустим, это сетевой драйвер, перехватывающий ввод-вывод для сетевых дисков и обрабатывающий его как-то особенно. Предположим также, что какая-то TSR-программа, запущенная в сеансе MS-DOS, перехватила int 21h, чтобы печатать на экран 1, когда int 21h вызывается, и 2, когда int 21h завершается. Проследим обращение к локальному диску (не сетевому, так что сетевой драйвер ничего не делает):


Заметьте, что всю работу по-прежнему делает 32-битная файловая подсистема. Вызов проходит по всей 16-битной цепочке только для поддержания иллюзии ответственности 16-битной MS-DOS. В 16-битном мире выполнялся только код, установленный TSR и драйвером, плюс маленький кусочек IFSMGR, связывающий компоненты. Никакой код 16-битной MS-DOS не выполнялся. 32-битная файловая система перехватила у MS-DOS всю работу.

Аналогичный танец «перехватить нормальную работу, но позволить необычные действия, если кто-то попросил необычные действия» происходил, когда подсистема ввода-вывода принимала управление вашим жёстким диском от 16-битных драйверов устройств. Если подсистема распознавала драйверы, она собирала их состояние и обрабатывала все операции так же, как 32-битная файловая подсистема обрабатывала операции вместо 16-битной MS-DOS. С другой стороны, если подсистема не распознавала какой-то драйвер, она оставляла его ответственным за диск. Компонент, передающий команды из 32-битной среды 16-битному драйверу, назывался RMM.

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

RMM, как ни странно, оказался полезен своей ужасностью, потому что его использование было ранним признаком заражения вашего компьютера MS-DOS-вирусом. В конце концов, MS-DOS-вирусы делали то же, что и TSR и драйверы: они перехватывали векторы прерываний и получали контроль над вашим жёстким диском. С точки зрения подсистемы ввода-вывода, они выглядели в точности как 16-битные драйверы жёсткого диска! Когда люди жаловались «Windows внезапно начала ужасно тормозить», мы направляли их на страницу производительности системы в панели управления и спрашивали, есть ли там строка «Часть дисков работает в режиме MS-DOS» или «Все диски используют режим совместимости с MS-DOS». Если есть, то за диски отвечал RMM, и если вы не меняли «железо», это, вероятно, означало вирус.

Наконец, некоторые части MS-DOS не имели отношения к вводу-выводу. Например, были функции выделения памяти, разбора строки с возможными шаблонными символами в формат FCB и тому подобные. Такие функции по-прежнему обрабатывались MS-DOS, поскольку это всего лишь функции «вспомогательной библиотеки» и ничего не выигрывали от переписывания в 32-битном коде, кроме возможности сказать «да, мы это сделали». Старый 16-битный код прекрасно работал, и использование готового кода позволяло сохранить совместимость с программами, патчившими MS-DOS с целью изменить поведение таких функций.

Первый комментарий к оригинальной статье: «Больше всего впечатляет, что бо́льшая часть этого бо́льшую часть времени действительно работала (в основном).»
Tags:
Hubs:
+95
Comments 21
Comments Comments 21

Articles