|
|||||||||||||
|
|||||||||||||
Операционные системы семейства NT используют гибридную архитектуру, сочетающую сильные стороны монолитных и микроядер, что теоретически должно обеспечить превосходство над монолитным Linux'ом (кстати говоря, экспериментальное ядро GNU/HURD построено как раз по микроядерной архитектуре). Легендарно устойчивую NT/XP, которую, как говорят, можно уронить только вместе с сервером, на самом деле очень легко вогнать в голубой экран. Достаточно любому драйверу сделать что-то недозволенное, как система автоматически катапультирует пользователя.
Аварийно завершить работу системы, выбросив синий экран, - самое простое, что только можно сделать при крахе системы. Microsoft неспроста пошла по пути наименьшего сопротивления. Мы же покажем, как выйти из голубого экрана в нормальный режим, чтобы успеть сохранить все данные еще до того, как система рухнет окончательно. Это довольно рискованный трюк. В случае провала мы можем потерять все, даже наш дисковый том, который потом придется очень долго восстанавливать.
Сначала мы продемонстрируем технику преодоления голубого экрана, а затем напишем специальный драйвер, который будет это делать автоматом.
[что нам понадобится]
Все эксперименты мы будем проводить на девственной Windows 2000, без установленных пакетов обновления (остальные системы ведут себя точно так же, отличаются только адреса). Чтобы ненароком не угробить основную систему, всю работу лучше всего выполнять на эмуляторе типа VM Ware, хотя это и необязательно.
Еще нам потребуется SoftICE, NT DDK и комплект утилит Свена Шрайбера из его книги «Недокументированные возможности Windows 2000».
[преодоление голубого экрана с помощью SoftICE]
Дождавшись окончания загрузки Windows 2000, мы запускаем драйвер w2k_kill.sys, позаимствованный у Шрайбера, специально спроектированный так, чтобы вызывать голубой экран. Разумеется, из командной строки просто так драйвер не запустишь! Без загрузчика тут никак не обойтись (можно, конечно, прописать драйвер в реестре, но тогда система будет падать при каждом запуске, что в общем-то не входит в наши планы). Воспользуемся динамическим загрузчиком w2k_load.exe, разработанным все тем же Шрайбером - w2k_load.exe. NT поддерживает динамическую загрузку драйверов, но готовой утилиты в штатный комплект поставки не входит - все в духе Microsoft, а вот в Linux с этим проблем нет.
Набираем в командной строке "w2k_load.exe w2k_kill.sys" и система успешно клеит ласты и падает в синий экран.
Так происходит потому, что в процессе инициализации драйвера-убийцы выполняются следующие строки, обращающиеся к нулевой ячейке памяти, что строго-настрого запрещено:
[фрагмент драйвера-убийцы, пытающийся прочитать двойное слово по нулевому указателю из режима ядра]
NTSTATUS DriverEntry (PDRIVER_OBJECT pDriverObject,
PUNICODE_STRING pusRegistryPath)
{
return *((NTSTATUS *) 0);
}
Ну и зачем было ронять систему из-за такой ерунды?! Кому наш страшный убийца реально мешает?! Ведь целостность системы ничуть не пострадала!
Если SoftICE был заблаговременно запущен, он отловит это исключение и покажет свой экран, передавая нам все бразды правления.
Если нажать «x» (или <Ctrl-D>), то немедленно после выхода из SoftICE вспыхнет синий экран, и чинить тогда будет уже нечего. Но пока мы находимся в отладчике еще можно кое-что предпринять. А предпринять можно следующее:
1) Определить место сбоя (обращение по нулевому указателю), исправить ситуацию (установить валидный указатель), вручную выйти из обработчика исключения, вернув CS:EIP на прежнее место: способ хороший, но, увы, требующий определенного интеллекта, которого у машины нет.
2) Зациклить текущий поток, воткнув в свободное место jmp $ и выйти из отладчика, разрешив прерывания командной r fl=I (если они вдруг были запрещены). Все будет ужасно тормозить, но ось продолжит работать и мы по крайней мере сможем корректно завершить ее работу.
3) Дождаться вызова функции KeBugCheckEx и сразу же выйти из нее, проигнорировав сбой и продолжив нормальное выполнение, правда, никаких гарантий, что система не рухнет окончательно, у нас нет.
4) Способ, предложенный ms-rem, дикий, но иногда работающий: отдать команды r eip=0/r cs=1B, переключающие процессор на прикладной режим.
Короче, вариантов много. Попробуем для начала воспользоваться первым способом. Мы знаем, что в данном случае авария произошла из-за ошибки нарушения доступа. Следовательно, процессор возбудил исключение, забросил на вершину стека EIP/CS/FLAGS и передал управление обработчику исключений, внутри которого мы сейчас и находимся.
Даем команду "d esp" для отображения содержимого стека и видим (для удобства рекомендую переключить окно дампа в режим двойных слов, воспользовавшись командой "dd"):
:d esp
0010:F7443C88 BE67C000 00000008 00200202 804A4431 ..g....... .1DJ.
0010:F7443C98 81116AD0 8649D000 BE8F1D08 BE8F1D08 .j....I.........
0010:F7443CA8 81480020 F7443D34 745FFFFF 83A49E60 .H.4=D..._t`...
Адрес инструкции, возбудившей исключение, лежит в первом двойном слове - BE67C000h (значение наверняка будет другим). Селектор CS идет следом. Он должен быть равен 08h. Третье двойное слово хранит содержимое регистра флагов - EFLAGS.
Теперь мы знаем место сбоя и можем вывести дизассемблерный листинг на экран. В этом нам поможет команда "u *esp" (дизассемблировать содержимое памяти по адресу, который содержится в регистре esp) или "u be67c000":
[определение реального места сбоя]
:u *esp
0023:BE67C000 MOV EAX,[00000000]
0023:BE67C005 RET 0008
0023:BE67C008 NOP
0023:BE67C009 NOP
0023:BE67C00A NOP
0023:BE67C00B NOP
Вот она! Инструкция, вызвавшая сбой! А давай ее перепрыгнем, продолжив выполнение с RET 08h? Но для начала нужно выйти из обработчика исключения. Для этого в SoftICE необходимо выполнить следующие команды:
1) r eip = *esp + sizeof(mov eax,[0]); // устанавливаем регистр EIP на RET
2) r cs = *(esp + 4); // устанавливаем селектор CS (не обязательно)
3) r FL = I; // разрешаем прерывания;
4) r esp = esp + C // снимаем со стека 3 двойных слова, заброшенные туда CPU
5) x // выходим из отладчика
После выполнения этой магической последовательности команд, система продолжит свою нормальную работу, и синий экран уже не появится.
Один маленький нюанс. Моя версия SoftICE не умеет восстанавливать регистр ESP в обработчике исключения. Отладчик игнорирует команду r esp=esp +C, на самом деле только имитируя ее выполнение! А это значит, что стек остается несбалансированным, и, несмотря ни на какие усилия медиков, система все-таки грохается. Приходится хитрить. Мы видим, что за RET 08h расположена длинная цепочка NOP'ов. А что если воткнуть сюда команду "ADD ESP,0Ch", чтобы стек сбалансировал сам процессор?
Говорим отладчику 'A BE67C008' (ассемблировать, начиная с адреса BE67C008) и вводим следующее: ADD ESP,0C<ENTER>JMP BE67C005<ENTER> и еще один <ENTER> для завершения ввода. Переустанавливаем EIP на начало нашей заплатки - r eip = BE67C008 и выходим из SoftICE. На этот раз у нас все получается!
Вот последовательность команд по реанимации системы. Напоминаю, что она применима только в этом случае:
[реанимация системы в условиях, приближенных к боевым]
u *esp
r eip = *esp
r eip = eip + 9
a eip
add esp,0c
jmp BE67C005h ; адрес команды RET 8, в твоем случае будет другим
<ENTER>
r fl=I
x
[автоматизируем нашу работу]
Способ ручного восстановления, только что описанный выше, хорошо сочетается с духом системных программистов, постоянно пасущих SoftICE и умеющих фехтовать регистрами, как рапирой. А вот простым юзерам такой подход смерти подобен. Но почему бы нам не написать для них утилиту, зацикливающую сбойный поток или замыкающую KeBugCheckEx?
Написать такую штуку несложно (и мы действительно напишем ее), но это все равно, что подложить полено под аварийный клапан. Если система пойдет вразнос, ее уже ничего не остановит. Может пострадать даже файловая система (пусть это будет хоть NTFS). Конечно, вероятность такой трагедии крайне мала, но она все-таки возможна - имей это в виду. Тем не менее, рискнуть все-таки стоит, особенно в тех случаях, когда ты уверен, что это можно сделать.
Вот, например, возник у меня как-то конфликт между криво написанным драйвером DSL-модема и драйвером видеокарты, а из-за этого при просмотре видео иногда выскакивал BSOD. Поскольку нормальных дров найти не удалось, я временно ограничился тем, что закоротил KeBugCheckEx перемычкой, изготовленной из команды JMP и, ты не поверишь, это прижилось!
Проведем следующий эксперимент. Нажмем <Ctrl-D> для вызова SoftICE, установим точку останова на KeBugCheckEx и запустим наш драйвер-убийцу. Причем точка останова обязательно должна быть аппаратной ("bpm KeBugCheckEx X"), а не программной (bpх KeBugCheckEx), иначе ничего не получится.
На этот раз вместо сообщения об ошибке страничного доступа, SoftICE всплывает по срабатыванию точки останова, высвечивая курсором первую команду функции KeBugCheckEx, которая в нашем случае располагается по адресу 8042BF14h.
Прокручивая окно дизассемблера вниз, находим первую инструкцию "RET 14h" (в нашем случае она располагается по адресу 8042C1E9h). Это и есть команда выхода из функции, на которую нужно сделать jmp. Для быстрого поиска можно попросить SoftICE сделать search ("s eip l -1 C2,14,00").
Говорим отладчику "r eip = 8042C1E9" (у тебя адрес, скорее всего, будет другим) и давим на <Ctrl-D> для выхода. Отладчик всплывает повторно в той же самой функции. У нас ничего не получилось?! Не торопимся с выводами! Все идет по плану! Игнорирование критических ошибок вызывает целый каскад вторичных исключений, что в данном случае и происходит. Повторяем нашу команду "r eip = 8042C1E9" (для этого достаточно нажать стрелку вверх/<ENTER>) и система возвращается в нормальный режим! Третий раз отладчик уже не всплывает. Мышь немного тормозит, однако гонять ее по коврику вполне реально.
Приступаем к созданию драйвера, который будет все это делать за нас. Для начала нам понадобится скелет. Выглядит он так:
[скелет псевдодрайвера, не управляющий никакими устройствами, но позволяющий нам выполнять код на уровне ядра]
.386 ; использовать команды .386 ЦП
.model flat, stdcall ; плоская модель памяти, stdcall-вызовы по умолчанию
.code ; секция кода
DriverEntry proc ; точка входа в драйвер
; код «драйвера»
;
…
…
…
; возвращаем ошибку конфигурации
mov eax, 0C0000182h; STATUS_DEVICE_CONFIGURATION_ERROR
ret ; выходим
DriverEntry endp
end DriverEntry
На самом деле это не совсем драйвер. Он не принимает никаких IRP-пакетов, не обслуживает никаких устройств и, вообще, не делает ничего, только загружается и выгружается. Но для нашей затеи этого будет вполне достаточно!
Весь код сосредоточен внутри процедуры DriverEntry (своеобразном аналоге функции main языка Си), которая выполняется при попытке загрузки драйвера, инициализируя все, что необходимо. Отсюда можно дотянуться до функции KeBugCheckEx и модифицировать ее по своему усмотрению.
Несмотря на то, что процедура DriverEntry выполняется на уровне ядра с максимальными привилегиями, попытка правки машинного кода приводит к нарушению доступа. Это срабатывает защита от непреднамеренного хака ядра некорректным драйвером. Как ее отключить?
Путь первый - через реестр. Создаем в разделе HKLM\SYSTEM\CurrentControlSet\Control\SessionManager\Memory Management значение типа REG_DWORD с именем EnforceWriteProtection и значением 0 (это можно делать и с прикладного уровня). Все! Запись в ядро открыта! Кстати говоря, SoftICE именно так и работает.
Путь второй - репаминг страниц. Отображаем физический адрес страницы, в которой лежит KeBugCheckEx, на виртуальное адресное пространство своего процесса посредством вызова функции NtMapViewOfSection, назначая все необходимые нам права. Репаминг осуществляется исключительно на уровне ядра, но к отображенной странице можно обращаться даже из прикладного уровня. Красота! По этой схеме работают многие брандмауэры и другие программы, нуждающиеся в перехвате ядерных функций, например, rootkit'ы.
Путь третий - сброс флага WP в регистре cr0. Это достаточно грязный трюк с целой свитой противопоказаний и рекламаций, однако для наших целей он вполне подходит. Используем его как самый простой и быстрый вариант, умещающийся всего в 3-х (!) машинных командах:
[код, отключающий защиту ядра от записи]
mov eax, cr0 ; грузим управляющий регистр cr0 в регистр eax
and eax, 0FFFEFFFFh; сбрасываем бит WP, запрещающий запись
mov cr0, eax ; обновляем управляющий регистр cr0
Соответственно, чтобы включить защиту, этот самый бит WP нужно установить, что и делают следующие машинные команды:
[код, включающий защиту ядра]
mov eax, cr0 ; грузим управляющий регистр cr0 в регистр eax
or eax, 10000h ; сбрасываем бит WP, запрещающий запись
mov cr0, eax ; обновляем управляющий регистр cr0
Политически корректная программа должна не просто отключать/включать защиту от записи, а запоминать текущее состояние бита WP перед его изменением, а затем восстанавливать его обратно, иначе можно непроизвольно включить защиту в самый неподходящий момент, серьезно навредив вирусу или rootkit'у.
Закоротить функцию KeBugCheckEx можно разными путями. Самое правильное (и надежное!) - определить ее адрес путем разбора таблицы импорта, но это слишком долго, муторно, нудно и утомительно. Гораздо проще подставить готовые адреса, жестко прописав их в своей программе. Минус этого решения в том, что на других компьютерах она работать не будет. Стоит установить (или удалить) какой-то ServicePack, перейти на другую версию системы, как все адреса тут же изменятся, и произойдет сплошной завис. Тем не менее, имея исходные тексты драйвера под рукой, его всегда можно исправить и перекомпилировать. Так что для домашнего использования такое решение вполне допустимо.
Главная тонкость в том, что мы не должны трогать первый байт функции KeBugChekEx, поскольку его уже потрогал SoftICE и весь вытрогал. Так же поступают и другие хакерские программы (например, API-шпионы), помещая сюда команду INT 03 (опкод CCh), предварительно сохранив прежнее содержимое где-то в другом месте.
ОК, пропустим первую команду (PUSH EBP) и начнем внедрение со второй. Чтобы сбалансировать стек в противовес PUSH EBP, говорим POP EAX, а затем либо jmp на RET 14h, либо сам RET 14h. Последний вариант короче и элегантнее. Реализуется он так:
[код, закорачивающий KeBugCheckEx]
mov dword ptr DS:[8042BF14h+1], 14C258h
Здесь: 8042BF14h - адрес начала функции KeBugCheckEx (на всех машинах разный), 1 - длина инструкции PUSH EBP, а 14C258h - машинный код, представляющий собой последовательность двух команд: POP EAX (58h)/RET 14h (C2h 14h 00h).
Объединив все компоненты воедино, мы получаем следующий папелац:
[средство против BSOD, перед употреблением встряхнуть]
.386
.model flat, stdcall
.code
DriverEntry proc
Mov eax, cr0 ; грузим управляющий регистр cr0 в регистр eax
mov ebx, eax ; сохраняем бит WP в регистре ebx
and eax, 0FFFEFFFFh ; сбрасываем бит WP, запрещающий запись
mov cr0, eax ; обновляем управляющий регистр cr0
mov dword ptr DS:[8042BF14h+1], 14C258h 14C258
; «закорачиваем» KeBugCheckEx
mov cr0, ebx ; восстанавливаем бит WP
mov eax, 0C0000182h ; STATUS_DEVICE_CONFIGURATION_ERROR
ret
DriverEntry endp
end DriverEntry
Вот такой маленький драйвер, а сколько данных он может спасти! Остается только откомпилировать его.
[ключи ассемблирования и линковки (используется пакет MASM из NT DDK)]
ml /nologo /c /coff nobsod.asm
link /driver /base:0x10000 /align:32 /out:nobsod.sys /subsystem:native nobsod.obj
Если все было сделано правильно, то на диске образуется файл nobsod.sys, который мы загрузим с помощью динамического загрузчика w2k_load. Загрузчик, конечно, заругается матом, что, мол, ERROR и драйвер вообще не грузятся, но так и должно быть. Все нормально! Мы же возвратили код STATUS_DEVICE_CONFIGURATION_ERROR!
Но, внимание! Под VM Ware такой трюк не срабатывает, поскольку она не полностью эмулирует регистр cr0 и таких шуток в упор не понимает, вызывая завис гостевой оси. В этом случае можно закомментировать все строки, относящиеся к регистру cr0 и отключить защиту через реестр, создав соответствующий ключ редактором. Кстати говоря, если на целевой машине установлен SoftICE, то такой ключ уже создан, и ничего делать не надо.
Загрузим драйвер-убийцу, чтобы проверить справиться ли с ним наше средство против BSOD или нет. SoftICE (если он установлен) несколько раз всплывает. Вот зануда! Гони его прочь, нажимая «x» или <Ctrl-D>. Все равно голубой экран уже не появляется! Система жутко тормозит, но работает. Плохо то, что теперь NT никак не может сигнализировать, что произошел системный сбой и что нужно побыстрее сматывать ласты, совершая shutdown. Кстати, почему это не может сигнализировать?! Самое простое - добавить в нашу заплатку на KeBugCheckEx несколько ассемблерных строк, которые «бибикнут» спикером или сыграют семь-сорок на динамике. В принципе, можно даже разделить BugCheck-коды на категории, каждой из которой будет соответствовать свое число гудков. За примерами далеко ходить не надо. Их можно выдрать из любого DOS-вируса. Техника программирования спикера на уровне ядра та же самая, и она ничуть не изменилась.
Да много что можно сделать! Главное - фантазию иметь!
[жизнь после BSOD]
Мы пережили самую страшную катастрофу - BSOD, после которой нам все по плечу! Конечно, неразумно практиковать такой подход на сервере, но для рабочих станций он вполне приемлем. Кстати говоря, некоторые вирусы, черви и rootkit'ы используют схожую технику для маскировки своего присутствия в системе. Некорректно написанный вирус может вызвать синий экран, и в системном журнале появится соответствующая запись, помогающая администратору разобраться с проблемой. Если же перемкнуть KeBugCheckEx, то компьютер будет просто беспричинно тормозить (или виснуть), но в журнале ничего не появится!
[чего не умеет NTFS]
Для минимализации последствий краха системы, NT поддерживает специальные call-back'и. Всякий драйвер может вызывать функцию KeRegisterBugCheckCallback и зарегистрировать специальный обработчик, который будет получать управление в момент возникновения голубого экрана. Это позволяет корректно останавливать оборудование, например, парковать головки жесткого диска. Шутка! А вот драйверу файловой системы сбросить свои буфера ничуть не помешало бы, тем более что он может проверить их целостность по CRC или любым другим путем. Ходят устойчивые слухи, что NTFS именно так и поступает. Как бы не так! Мыщъх дизассемблировал NTFS.SYS и не нашел там никаких признаков вызова KeRegisterBugCheckCallback! В момент аварии буфера NTFS остаются не сброшенными, и она выживает только благодаря поддержке транзакций, при которых гарантируется атомарность всех операций, то есть операция либо выполняется, либо - нет. Обновление файловой записи не может произойти наполовину, и потому, в отличие от FAT, потерянные кластеры на ней не образуются. Ну, практически не образуются.
(с) Leonid Loiterstein
Всегда ли помогает шунтирование KeBugCheckEx? Насколько это безопасно? Это очень опасно, тем более далеко не всегда помогает. Вот, например, рассмотрим следующий пример кода, позаимствованный из ядра:
[фрагмент кода, при котором шунтирование KeBugCheckEx заканчивается очень печально]
00565201 call ExAllocatePoolWithTag ; выделение памяти
00565206 cmp eax, ebx ; проверка успешности выделения памяти
00565208 mov ds:dword_56BA84, eax
0056520D jnz short loc_56521C ; -> нам дали память
0056520F push ebx ;
00565210 push ebx ;
00565211 push 6 ; с памятью вышел облом
00565213 push 5 ; отправляемся на небеса
00565215 push 67h ;
00565217 call KeBugCheckEx ;
0056521C loc_56521C: ; CODE XREF: sub_5651C1+4C j
0056521C lea eax, [ebp+var_C] ; продолжаем нормальное выполнение
0056521F push ebx
00565220 push eax
Система выделяет память из общего пула, и если с памятью не облом, то происходит нормальное продолжение, в противном случае вспыхивает голубой экран. Допустим, мы закоротили KeBugCheckEx, что тогда? Нас обломали на память, а мы продолжаем нормальное выполнение, как ни в чем не бывало, обращаясь по указателю, который указывает в никуда. Возникает целый каскад вторичных исключений, а все структуры данных превращаются в труху, и система рушится окончательно.
Рождение и становление операционной системы - это зачастую долгий эволюционный процесс, длящийся десятилетиями: одну версию ОС сменяет следующая, добавляются новые элементы и детали а потом. семейство вымирает. Операционные системы не появляются "вдруг" или "из ниоткуда", если проследить их историю, то всегда можно узнать, откуда, как говорится, уши растут. А обычно эти самые уши растут из ранних версий малораспространенных, но компактных и быстрых операционок. Так, собственно, нb для кого это не секрет, что "Майкрософт" разработал свой легендарный DOS (Disk Operation System) на основе кода, купленного за $50000 у небольшой фирмы с названием Seattle Computer Products, a Windows - уже на основе DOS. Linux, значение и место на рынке которого сейчас очень трудно оценить однозначно, изначально был ни чем иным, как изощренной фантазией Линуса Торвальдса на тему операционной системы Minix - упрощенной версии UNIX. Конечно, в процессе своей эволюции и становления от первоначального "праотца" остается очень мало, код переписывается множество раз, добавляются новые возможности, идеи, реализации. Но все же зачастую некоторые рудименты остаются - это, в первую очередь, идеи дизайна операционной системы - темное наследие прошлых лет. Как известно? из рубахи очень сложно сделать штаны, сколько новых карманов ни пришивай и пуговиц ни спарывай, их лучше будет сшить заново. Так же сложно изначально однопользовательскую и однозадачную операционную систему превратить в многопользовательскую и многозадачную, да еще и стабильную сетевую платформу. Именно поэтому семейства операционных систем сменяют друг друга, приходят новые концепции и парадигмы, затрагивающие как строение ОС, так и стили программирования под эти платформы, но всегда остается нечто неуловимое, ускользающее от пристального взора, что объединяет целые семейства операционных систем. Для Windows это очень характерно, поэтому важно отдавать себе отчет, что общего в старых и новых системах и чем они различаются. Операционки проходят пору детства, полную многочисленных ошибок периода роста и недоработок, стадию зрелости, когда большинство ошибок исправляется, механизмы настройки и работы продумываются до мелочей, и этап старости, когда система уже не в состоянии нормально справляться с растущими задачами и потребностями пользователей. Новые возможности реализуются обычно в виде заплат, и чаще всего сделано это бывает "через одно место", так как их нормальная реализация изначально не была даже предусмотрена разработчиками, вследствие чего она и невозможна без кардинальной и полной переработки всего ядра. Так, для семейства Windows 9х (а мы все же склонны отделять его историю от истории DOS, хотя для этого нет особых оснований, кроме исключительно психологических), win3.1 - было детством, win95 - юностью, win98 - зрелостью... Билл Гейтс вкупе со Стивом Балмером, как известно, хотели вычеркнуть "старость" и обещали похоронить все семейство win9x, сделав win98 последней версией старой платформы. Но обещанного, как известно, три года ждут, особенно, если имеешь дело c такой непредсказуемой компанией, как "Майкрософт"... На свет появились и Win98SE (которая, между прочим, все еще установлена на большинстве домашних компьютеров пользователей и даже в мелких организациях), и мертворожденный младенец Win ME, и Win CE. Впрочем, все эти подрумяненные релизы старой ОС лишь ненадолго продлили ее агонию: становится совершенно очевидно, что времена win9x ушли, и час ее, как говорится, пробил. Будущее за операционными системами другого поколения, и это вовсе не обязательно будут продукты от "Майкрософт". Но и им, в свою очередь, есть что предложить взамен устаревшему продукту.
Несмотря на - или, может быть, - благодаря стремительному успеху серии Win3.1, позже преобразованной в Win95 и Win98, который превзошел ожидания даже своих создателей, "Майкрософт" разработала другую ветвь своих продуктов - WinNT (где NT означает New Technology). Грубо говоря, заслуга разработки семейства NT принадлежит даже не совсем "Майкрософт", точнее, не одной только "Майкрософт", так как изначально работы по созданию операционной системы следующего поколения велись совместно как программистами и дизайнерами из команды знаменитого Дэвида Катлера (Dave Cutler), так и специалистами голубого гиганта (IBM). Перед всеми этими, безусловно, по-своему талантливыми людьми стояла задача разработать NT так, чтобы она удовлетворяла пяти основным требованиям:
Основываясь на своем опыте работы с операционными системами в DEC (Digital Equipment Corporation), Катлер основной приоритет придавал проектированию операционной системы, поскольку он прекрасно сознавал, что создаваемый его группой код будет использоваться очень долго. Вследствие этого он пытался создать хорошо и цельно спроектированную систему, в противоположность тому варианту, который бы оптимально работал, в первую очередь, с оборудованием, имевшимся на тот момент времени. Кроме того, с самого начала предполагалось, что система будет предназначена для работы в качестве сервера сети, или, на худой конец, рабочей станции, следовательно, к ней предъявлялись исключительно жесткие требования относительно надежности и безопасности. А так как она должна была быть еще и переносимой, Катлер не разрешал сотрудникам оптимизировать код на ассемблере, поскольку он был бы аппаратно-зависимым. Подобный подход к проектированию операционной системы привел к тому, что первые версии Windows NT работали очень медленно даже на самых производительных персональных компьютерах того времени. Но тут сыграли свою роль два фактора: во-первых, разработчики, увидев, насколько громоздкой получилась система, существенно ее оптимизировали, а во-вторых, появились более мощные компьютеры, и проблема производительности решилась сама собой. Вслед за этим начали проявляться приятные свойства NT: разработчикам не нужно было переписывать часть кода ядра системы, достаточно было перекомпилировать уже давно отлаженный исходный код, используя более "свежий" оптимизирующий компилятор языка высокого уровня. В то же время не прекращались работы по уменьшению размера системы, повышения ее быстродействия и, разумеется, надежности (проект Daytona, названный в честь автострады во Флориде), но при этом оптимизировался не низкоуровневый код под конкретный процессор, а высокоуровневый, который работал бы быстрее на любых машинах.
Идея оказалась действительно удачной. Качество конечных продуктов сильно улучшилось, к тому же код на Си выглядел более понятным и удобоваримым, чем набор инструкций на ассемблере, а значит, подобный подход позволял с большей легкостью и оперативностью вносить изменения в ядро, при этом допускалось меньшее количество ошибок. Недаром именно так пишутся практически все современные операционные системы, начиная от Linux и заканчивая Solaris, FreeBSD и BeOs. Теперь же, бросая взгляд в прошлое, можно с уверенностью сказать, что такая установка полностью себя оправдала и в случае с творением "Майкрософт", поскольку базовая внутренняя архитектура Windows 2000 (Windows XP) принципиально не изменилась по сравнению с Windows NT, за исключением добавления поддержки Plug and Play и ACPI.
Можно констатировать, что на сегодняшний день операционные системы на основе технологии NT являются наиболее производительными, масштабируемыми и, что самое главное, хорошо отлаженными и проверенными из всех, которые когда-либо выпускала "Майкрософт". Безусловно, "Майкрософт" не единственный производитель операционных систем, но именно эта компания является фаворитом на рынке десктопных операционок, то есть операционных систем, устанавливаемых преимущественно на домашних компьютерах пользователей и применяемых в сфере малого и - частично - среднего корпоративного бизнеса. И сильных конкурентов в этом (наиболее интересующем нас) секторе рынка у нее, к сожалению, пока нет. Положение с OS/2 - хуже некуда, IBM фактически отказалась от дальнейшего развития этой платформы, BeOS канула в лету, Linux при всем нашем уважении к нему, все же борется за совершенно другую часть рынка, рынка серверных операционных систем, предназначенных скорее либо для крупного бизнеса, либо для информационных систем среднего уровня ответственности. И что бы там нb говорили оголтелые фанаты пингвинов и FreeBSD'шных чертиков, некоторая часть серверов функционирует все же под управлением NT, а не UNIX. Поэтому выход каждой новой версии Windows является очень интригующим и волнующим широкие массы общественности событием. Тем более что Windows 2000 - это не только очередной главный выпуск операционной системы Windows NT, она также рекламируется "Майкрософт" как самое существенное из всех обновлений NT. Даже в рекламу так разукрашенной и размалеванной Windows XP "Майкрософт" не вложила столько же средств и усилий. Как мы видим, "мелкомягкие" намериваются сделать эту операционную систему базой для всех своих будущих решений (о чем они и сами заявляют): от потребительских продуктов до высокопроизводительных серверов, причем уже сейчас сделаны серьезные шаги в этом направлении. На самом деле, даже Windows 2000 - это не одна операционная система, а четыре, собранныt на одном ядре: Professional, Server, Advansed Server и Datacenter Server. Windows 2000 Professional - наиболее популярная на сегодня - действительно, как следует из названия, предназначена для установки либо на небольшие изолированные компьютеры профессиональных или причисляющих себя к таковым пользователей, либо на клиентские компьютеры в сети. Самая же мощная - Advanced Server - может устанавливаться на крупные сетевые серверы. Ее мощностей вполне хватит даже на крупную корпорацию, судите сами: возможность создания масштабируемых кластерных систем (возможность построения систем с высокой частотой запросов, до 4 узлов); корпоративная архитектура памяти (всего - до 64 Гбайт физической памяти); масштабируемая мультипроцессорная симметричная обработка, поддержка до 32 процессоров. Вопрос только в том, будут ли операционные системы от "Майкрософт" использовать в крупных корпорациях. Но если "Майкрософт" при разработке новых операционных систем будет придерживаться той же политики, которой она придерживалась при создании Windows 2000, она сможет вернуть доверие, утраченное из-за не очень стабильной работы win9x. Так что, нравится вам это или нет, один из вариантов Windows 2000 предназначен стать в будущем вашей настольной (или не очень) операционной системой (если вы, конечно, придерживаетесь операционных систем от "Майкрософт"), а потому, как нам кажется, возможности этой, бесспорно, качественной операционной системы следует рассмотреть повнимательнее.
WinNT всегда отличалась в лучшую сторону от своей, так сказать, "домашней сестры" - Win 95 - 98. Это и более надежное ядро, и полностью реализованный защищенный режим, и повышенная безопасность. Кроме того, файловая система NTFS (что расшифровывается как NT File System) дает гораздо больше возможностей, чем устаревшая FAT16 или пришедшая ей на смену FAT32; с ней вам не придется больше беспокоиться о вечно потерянных цепочках и кластерах. Традиционно первые системы NT использовались почти исключительно на серверах, там, где было неудобно или по каким-то причинам невозможно применение UNIX. Но, как известно, ничто не живет в человеке так долго, как старые привычки и традиции, поэтому даже сейчас можно очень часто слышать высказывания типа: "Зачем мне дома Win2000, я же играть собираюсь..." Конечно, у каждого свои запросы, но если вам нужна безопасность данных, и вы не хотите, чтобы "злые хакеры" запросто смогли узнать ваш пароль на доступ к Интернету, или вам надоели постоянно зависающие приложения то, возможно, вам следует подумать об установке новой операционной системы. Ну а если вы используете компьютер на работе, и вам важна конфиденциальность и, главное, сохранность информации, то причин использовать именно NT у вас становится еще больше. Еще одно преимущество Win2000 - она официально локализована для русскоязычных пользователей, причем не только настольный вариант, но и более мощные серверные версии.
Если с отличиями от серии 9x все более или менее понятно - Windows 2000 имеет принципиально другое внутреннее устройство, подробнее про которое будет написано чуть ниже - то об отличиях от NT 4.0 нужно поговорить отдельно. В первую очередь, следует упомянуть следующие элементы, которые подверглись изменению:
- Графический интерфейс - интерфейс был оптимизирован для упрощения доступа к информации посредством личных меню и списков последних по времени использования приложений.
- Поддержка оборудования - добавлена поддержка Plug and Play (PnP), Advanced Configuration and Power Interface (ACPI), USB, IEEE 1394 (FireWire), а также новая модель драйверов мультимедиа-устройств (WDM).
- Простота конфигурирования - усовершенствованны средства установки и конфигурирования приложений и аппаратных устройств.
- Простота администрирования - введение консоли управления Microsoft Management Console (MMC).
Также нужно отметить тот факт, что благодаря многочисленным изменениям во внутренних алгоритмах работы, Windows 2000 стала работать быстрее и эффективнее, чем NT 4.0 (в основном это касается приложений, использующих графику и, в том числе, графический интерфейс GUI). Немаловажен и тот факт, что теперь вам гораздо реже придется перезагружать систему после внесения каких-либо изменений в настройки ее работы.
На этом, на наш взгляд, можно завершить краткое описание Windows 2000, надеюсь, мы ввели вас в курс дела относительно истории ее разработки и смогли убедить в преимуществах использования именно этой версии. Впрочем, не будет лишним еще раз напомнить, что мы обсуждаем Windows 2000, а не ХР, потому что она является СЕРВЕРНОЙ операционной системой и "Майкрософт" уделяет значительно больше внимания устранению ошибок и технической поддержки Windows 2000. Тем не менее, из-за того что системы 2000 и XP имеют схожее строение, почти всегда мы употребляем первую, можно смело ставить и вторую - справедливость сказанного не изменится.
Сначала я приведу очень упрощенную (рис.1), однако вполне достаточную для понимания основных принципов функционирования ОС схему архитектуры Windows NT (начиная с NT 4.0). Обратите внимание на линию, разделяющую части кода, выполняющиеся в разных режимах процессора. Прямоугольники над этой линией соответствуют процессам пользовательского режима, компоненты под ней — сервисам режима ядра. Главное отличие этих режимов состоит в том, что код, работающий в режиме ядра, получает доступ ко всем ресурсам ОС и оборудованию, а код пользовательского режима способен лишь вызывать сервисы ОС для манипуляции с оборудованием или внутренними структурами системы. Причем как ядро, так и каждый процесс (задача, приложение) имеет собственное виртуальное адресное пространство. Из всего этого делаем важный вывод: нарушить работу системы может только код режима ядра, пользовательский же код при всем своем желании не может повредить не только систему, но и другие работающие приложения (за исключением разделяемой памяти). Еще один важный момент: ядро ОС (точнее, исполнительная система и микроядро) и драйверы работают в одном адресном пространстве, причем в целях повышения быстродействия в режиме ядра не проводится никаких проверок на правильность передачи параметров процедурам и т.д., что в случае некорректно работающего драйвера может привести к катастрофе — сбою в режиме ядра (ошибка STOP, пользователи обычно называют это Синим Экраном Смерти — BSOD, хотя машина еще вполне работоспособна, и с помощью второго компьютера и отладчика можно найти и устранить проблему). Таким образом, добавление драйвера устройства — единственный способ добавить в систему код режима ядра и в то же время единственный способ “грохнуть” по-настоящему вашу NT, так как при таких сбоях, во-первых, восстановление почти невозможно, а во-вторых, дальнейшая работа может привести к еще большим повреждениям, в том числе и пользовательских данных, что недопустимо. Для предотвращения таких ситуаций Microsoft придумала систему верификации и подписывания драйверов. Сначала компоненты драйвера проходят тест в лабораториях WHQL (Windows Hardware Quality Laboratory) и в случае его успешной сдачи подписываются этой лабораторией как совместимые с данной версией Windows. При установке драйвера в систему ОС проверяет его подпись. Если она есть и является верной и действительной, драйвер устанавливается без вопросов, если есть какие-то проблемы с этим — все зависит от принятой политики подписывания драйверов (отказ от установки, запрос пользователю на установку, установка без запроса). Следует отметить, что данное нововведение появилось в Windows 2000. Ну, а сейчас мы быстро пробежимся по основным компонентам системы.
Фиксированные процессы поддержки системы, например, диспетчер сеансов. Необходимы для нормальной работы системы. Имеют доступ напрямую к некоторым сервисам ОС, т.е. являются привилегированными процессами.
Процессы сервисов (сервисы Win32). Иначе называются службами. Пример — Планировщик задач. Работают в фоновом режиме, без интерактивного взаимодействия с пользователем.
Пользовательские приложения. Бывают пяти видов: Win32, Windows 3.1, MS-DOS, POSIX и OS/2.
Подсистемы окружения. Образуют окружение операционной среды, предоставляя сервисы ОС. Существует 3 подсистемы: Win32, POSIX и OS/2.
Обратите внимание на прямоугольник с DLL-подсистем. Дело в том, что процессы пользовательского режима не могут вызывать сервисы ядра ОС напрямую, вместо этого они используют DLL (Dynamically Loadable Library — динамически загружаемая библиотека) соответствующих подсистем окружения.
Исполнительная система. Содержит базовые сервисы ОС (управление памятью, процессами и потоками, защиту, ввод/вывод и взаимодействие между процессами).
Ядро — низкоуровневые функции ОС (планирование потоков, диспетчеризация прерываний и исключений и т.д.). Предоставляет набор процедур и базовых объектов исполнительной системе для реализации более сложных структур.
Драйверы устройств. Драйверы как аппаратных устройств, транслирующих стандартные запросы программ в специфичные запросы ввода/вывода к конкретному оборудованию, так и сетевые драйверы и драйверы файловых систем.
Уровень абстрагирования от оборудования. Изолирует другие компоненты режима ядра от специфики оборудования данной платформы.
Подсистема поддержки окон и графики. Реализует функции графического интерфейса пользователя (GUI). Обеспечивает поддержку окон, элементов управления пользовательского интерфейса и отрисовку графики.
Итак: что хорошего предлагает нам Windows 2000? В первую очередь, это, конечно, защищенность данных и отказоустойчивость. Звучит хорошо, но вдумчивого и любопытного читателя должно интересовать, что же стоит за общими словами и заявлениями рекламных представителей "Майкрософт". "Да, масштабируемость; да, высоко-производительность; да, повышенная надежность... все это мы уже слышали тысячи раз, и тысячи раз потом снимали лапшу с ушей и имели на деле то, что имели... - может сказать он. - А что же по существу?" - и будет совершенно прав. Голые слова, не подкрепленные фактами, так и останутся бесполезным сотрясанием воздуха. По существу же, мы имеем операционную систему, в которой разработчики, по крайней мере, попытались применить на практике очень разумные идеи, повышающие стабильность системы и ее помехозащищенность. Данные и код операционной системы изолированы от пользовательских приложений целым рядом специальных методов. Для предотвращения доступа приложений к критически важным данным операционной системы и устранения риска их модификации Windows 2000 использует два режима доступа к процессору: пользовательский и режим ядра. Стоит заметить, что хотя на самом деле в архитектуре процессоров x86 предоставлено четыре уровня привилегий (так называемых колец), на которых могут работать процесоры, "Майкрософт" поступила, как всегда, достаточно оригинально, и решила использовать только два из них: нулевой уровень для исполнения в режиме ядра и третий - для пользовательского режима. С другой стороны, разработчиков тоже можно понять: мечта о мировом господстве на рынке операционных систем не дает им покоя, поэтому NT разрабатывалась так, чтобы работать не только на процессорах фирмы Intel, но также, например, на Digital Alpha или IBM PowerPC, которые могли иметь только два уровня привилегий. Как уже упоминалось, Windows 2000 основана на концепции микроядра (microkernel), а значит, разработчики ОС постарались минимизировать объем кода, исполняемый в режиме супервизора, то есть в режиме, при котором код обладает возможностью прямого доступа ко всему аппаратному обеспечению и ко всей памяти. Естественно, что в таком случае только данный код может управлять работой всех устройств и предоставлять программам базовые сервисы, такие, как, например, выделение (или отказ в выделении) памяти, доступ к дисковой подсистеме и т. д. От работоспособности микроядра полностью зависит работоспособность компьютера в целом, поэтому к нему предъявляются достаточно высокие требования:
Все эти показатели, за исключением, быть может, объема кода, у Win2000, на наш взгляд, находятся на достаточно хорошем уровне, хотя мнения могут быть разными, так как оценка, по сути, является в большой мере субъективной.
Концепция микроядра подразумевает, что фактически все компоненты операционной системы, за исключением небольшого базового программного модуля (который и является микроядром), работают в пользовательском режиме на равных условиях со всеми остальными программами, работающими в системе. Очевидно, что отказоустойчивость всей системы при таком подходе возрастает, так как сбой одного из компонентов приводит к минимальному ущербу, при этом всегда остается возможность этот компонент перезапустить. Грубо говоря, если только ядро осталось после сбоя "живым", нажатие Ctrl+Alt+Del приведет к появлению окна "Безопасность Windows", с помощью функций которого можно решить большинство проблем, причем это произойдет немедленно, так как соответствующий поток процесса ядра при обычных условиях имеет наивысший приоритет. Если же вы обладаете правами администратора, у вас есть очень простой способ "подвесить" систему: нужно всего-то написать программу, которая будет к некоторому числу добавлять по единичке, пока не будет достигнуто значение, скажем, 1045 (те, кто хоть раз занимался программированием, меня поймут).
После чего эта программа запускается, и ей ручками присваивается приоритет 31 - REALTIME_PRIORITY_CLASS и любой текущий исполняемый поток, имеющий, соответственно, меньший приоритет, прерывается до истечения отведенного ему кванта времени, а код и данные операционной системы блокируются. Все очень просто, но если уж компьютер завис, то винить надо будет себя, а не "Майкрософт". Кстати, на этом примере видно, что нужно быть очень внимательным при установке высоких приоритетов и режима реального времени программе - если уж она "зависнет", то наступит крах системы.
Но вернемся к микроядру. Кроме всего прочего, система, основанная на концепции микроядра, позволяет производить более гибкое конфигурирование, так как любой из компонентов ОС можно легко заменить на другой, поддерживающий точно такой же программный интерфейс. На самом деле, для увеличения производительности Windows 2000 использует некий гибрид микроядра и монолитного дизайна, так как некоторые ее базовые компоненты, например, диспетчер процессов и диспетчер виртуальной памяти, все-таки функционируют в режиме ядра - это позволяет им взаимодействовать между собой не через медленные механизмы межпроцессорной передачи данных (передачи данных между несколькими программными процессами), а используя общую память. Вторая причина включения дополнительного кода в режим ядра кроется в том, что процессор, занятый выполнением некоторой задачи, реализуемой соответствующим процессом (или, как говорят, работающий в определенном контексте), работает с текущими значениями процессорных регистров, а также указателей на используемую память (стек, данные, исполняемый код). Эти значения различны для различных потоков, поэтому, прежде чем перейти на выполнение другой программы, реализуемой другим процессом, процессор должен сохранить текущий контекст, а затем загрузить контекст нового процесса, на выполнение которого он переключается. Данная процедура называется переключением контекста и может занимать существенное время. Использование гибридного дизайна позволяет снизить количество переключений контекста. Хотя, теоретически и это несколько, снижает надежность системы, все равно она оказывается не в пример больше, чем у windows 9x. За счет полностью реализованного режима виртуальной машины микроядра обеспечиваются многие дополнительные возможности, недоступные, скажем, Win98. Это, в первую очередь, обеспечение приложениям индивидуального адресного пространства для каждого процесса и предоставление уровня защищенности не хуже, чем по стандарту C-2/Е-3, здесь ключевую роль играет то, что Wind2К отказывает процессам, обращающимся к оборудованию и памяти, которые им не принадлежат. Достигается это достаточно простыми методами, например, каждая страница в виртуальной памяти помечается тэгом, определяющим, в каком режиме должен работать процессор для чтения или записи данной страницы памяти. Таким образом, страницы системной памяти оказываются недоступными для всех процессов, не работающих в режиме ядра. При попытке выполнения любой запрещенной операции центральный процессор автоматически генерирует исключение, и управление передается микроядру NT. Микроядро определяет, разрешено вызвавшей исключение программе выполнять такую операцию, или нет. Если операция признана несанкционированной, управление передается программе Dr.Watson, которая оповещает о возникшей ошибке пользователя, а система в этот момент быстренько завершает работу приложения, попытавшегося выполнить незаконное с точки зрения ОС действие. Естественно, подобный алгоритм работы - это не особая и сверхгениальная разработка талантливых программистов из "Майкрософт", а хорошая реализация тех аппаратных возможностей "железа", которые появились в современных микропроцессорах.
Для того чтобы обратиться к оборудованию или памяти, а также совершить некоторые другие операции, недоступные в пользовательском режиме, приложения (а также многие подсистемы самой Windows 2000, которые не работают в режиме ядра) обращаются к системным вызовам микроядра ОС, которые также называют естественным API. В состав этого API входит более 250 функций, обращение к которым осуществляется при помощи системных вызовов, основанных на программных исключениях. Все вызовы API обслуживаются как системными службами NT, так и модулем NT Executive - "сердцем" операционной системы, над которым так дорожит и трясется "Майкрософт".
Модуль NT Executive представляет собой несколько программных потоков, которые закоренелые программисты-системщики почему-то предпочитают называть рабочими потоками; естественно, все эти потоки выполняются в режиме ядра. Код практически всех подсистем этого модуля находится в файле ntoskrnl.exe, кроме, разве что, подсистемы win32, код которой расположен в файле win32k.sys, и уровня абстракции оборудования HAL (Hardware Abstraction Layer), который содержится в файле halxxxxx.dll, где xxxxx зависит от типа используемого компьютера. NT Executive сосредотачивает все самые важные части ОС:
- Ядро - это основная часть Windows 2000, в реализации которой кроется вся мощность и красота платформы NT. Прежде всего, ядро отвечает за выделение памяти для приложений и распределение процессорного времени, то есть, фактически, за реализацию многозадачности. Для этого в состав ядра входит так называемый планировщик потоков (threads scheduler), который назначает каждому из потоков один из 32 уровней приоритета. Уровень 0 зарезервирован для системы. Уровни от 1 до 15 назначаются исполняемым программам, а уровни от 16 до 31 могут назначаться только администраторами. Планировщик делит все процессорное время на кванты фиксированного размера (как менять размер кванта, еще будет рассказано в следующих частях нашей статьи), при этом каждый программный поток выполняется только в течение отведенного ему времени, и если к окончанию кванта он не освобождает процессор, планировщик в принудительном порядке приостанавливает этот поток и меняет контекст процессора, настраивая его на выполнение другого потока, обладающего тем же приоритетом. Ядро также осуществляет всю работу, связанную с обработкой программных и аппаратных прерываний.
- Уровень абстракции оборудования (HAL) - это прослойка между операционной системой и аппаратурой компьютера. HAL имеет свой собственный API, предназначенный для транслирования обращений всех приложений и драйверов в конкретные команды процессора, учитывающие его внутреннюю структуру и нюансы работы. HAL и ядро написаны на языке низкого уровня, в то время как остальные компоненты ОС реализованы на языке C и C++, поэтому именно они отвечают за переносимость NT на системы с другой архитектурой. На данный момент Windows 2000 есть в версиях как для процессоров PC совместимых компьютеров (Pentium и старше), так и для нового перспективного семейства 64-битных процессоров EPIC (Itanium, Itanium-2).
- Диспетчер ввода-вывода (I/O Manager) - интегрирует добавляемые в систему драйверы устройств в операционную систему Windows 2000.
- Диспетчер объектов - служит для управления всеми разделяемыми ресурсами компьютера. В момент обращения приложения или службы к какому-либо ресурсу, диспетчер объектов сопоставляет этому ресурсу объект и отдает приложению дескриптор этого объекта. Используя дескриптор, приложение взаимодействует с объектом, совершая в его отношении различные операции. Монитор системы безопасности следит при этом за тем, чтобы с объектом выполнялись только разрешенные действия.
- Диспетчер процессов - предоставляет интерфейс, при помощи которого другие компоненты Windows NT Executive, а также приложения пользовательского режима могут манипулировать процессами и потоками. Во время работы диспетчер процессов сопоставляет каждому процессу и потоку идентификатор процесса (PID - Process Identifier) и потока (TID - Thread Identifier) соответственно, а также карту адресов и таблицу дескрипторов.
- Диспетчер виртуальной памяти - служит для управления и организации подсистемы памяти, позволяет создавать карты адресов для процессов и следит за корректностью использования адресного пространства приложениями (то есть, следит за общим доступом к памяти и осуществляет защиту страниц в режиме копирования при записи). Диспетчер виртуальной памяти также обеспечивает возможность отображения файлов на память, используемую для загрузки в оперативную память исполняемых файлов и файлов динамических библиотек. Еще в Windows NT4.0 существовала так называемая Защищенная Модель памяти, которая (в отличие от DOS-подобных ОС) позволяла изолировать каждый процесс друг от друга и, что самое главное, от кода самой ОС. Диспетчер виртуальной памяти представляет физическую память для пользовательских приложений таким образом, что каждому процессу выделяются отдельные 4Гб виртуального адресного пространства, из которых младшие 2Гб используются непосредственно процессом по своему усмотрению, а старшие 2Гб - отводятся под нужды системы, причем они - общие для всех процессов. При этом каждый процесс "думает", что он - единственный, запущенный в системе. Но здесь кроется некоторое затруднение: многие 16-разрядные программы при своей работе обмениваются данными между собой напрямую, используя одни и те же участки памяти, а это неприемлемо для Windows NT. В этом случае такие программы все же запускаются и предоставляют разделяемую память, где они могут обмениваться данными. Эта память является нестраничной областью физической памяти, которая может быть спроецирована на виртуальное адресное пространство нескольких процессов, и таким образом они смогут взаимодействовать друг с другом. Как мы видим, самое главное, чем занимается диспетчер виртуальной памяти - это видно из его названия - организация логической памяти, размер которой больше размера физической, установленной на компьютере. Этот трюк достигается благодаря тому, что страницы памяти, к которым долго не было обращений и которые не имеют атрибута неперемещаемых, сбрасываются диспетчером в файл pagefile.sys на винчестер и удаляются из оперативной памяти, освобождая ее для других приложений. В момент, когда происходит обращение к данным, находящимся в перемещенной на винчестер странице, диспетчер виртуальной памяти незаметно для приложения копирует страницу обратно в оперативную память, и только затем обеспечивает доступ к ней. Этот механизм обеспечивает выделение дополнительной памяти программам, которые нуждаются в ней, и при этом следит за тем, чтобы все работающие в системе программы обладали достаточным объемом физической памяти для того, чтобы продолжать функционирование.
- Диспетчер кэша - применение кэшированного чтения и записи позволяет существенно ускорить работу таких устройств, как винчестеры и CD-ромы. При этом наиболее востребованные файлы дублируются диспетчером кэша в оперативной памяти компьютера, и обращение к ним обслуживается с использованием этой копии, а не оригинала, расположенного на сравнительно медленном долговременном носителе. Кэш в Windows 2000 является единым для всех логических дисков, вне зависимости от используемой файловой системы, при этом теперь используется файлово-ориентированный, а не блочно-ориентированный алгоритм работы. Кроме того, он является динамическим, а это значит, что диспетчер управляет его размерами в зависимости от доступного объема свободной физической памяти в каждый конкретный момент.
- Win32 User и GDI - выполняют все функции, связанные с пересылкой системных сообщений и отображением информации на экране. До Windows NT 4 эти серверные компоненты функционировали в пользовательском режиме в качестве одной из составных частей подсистемы Win32.
- Другие (монитор обращений к системе безопасности, механизм локального вызова процедур, диспетчер конфигурации, диспетчер PnP, диспетчер электропитания, аппаратные драйверы и т. д.).
Остальные компоненты операционной системы выполняются в пользовательском режиме, часто их называют подсистемами. Например, в состав Windows 2000 входит подсистема безопасности и подсистемы, предоставляющие программам функции таких распространенных операционных сред, как DOS, OS/2, Win16, POSIX, а также Win32. Основное назначение операционной среды - предоставления интерфейса, а также эмуляция работы операционных систем, отличающихся от Windows 2000. Проще говоря, операционная среда добавляет в систему Windows 2000 дополнительные возможности и новые системные вызовы, отличающиеся от вызовов естественного API-ядра. Подсистемы операционных сред загружаются только в случае, если возникнет необходимость их использования. Каждая подсистема выполняется как отдельный процесс пользовательского режима. Таким образом, каждая подсистема защищена от сбоев, вызванных другими подсистемами, именно благодаря этому платформа Win2К функционирует более стабильно, чем операционные системы линейки Win9x. Что кажется наиболее удивительным, Win32 API не является родным для Windows 2000, а реализован так же, как и, скажем, поддержка DOS API. Это замечание, однако, не совсем верно: естественный API очень похож на Win32 API, тем не менее, с ним несколько сложнее работать (между некоторыми функциями Win32 и некоторыми функциями естественного API может существовать взаимооднозначное соответствие, однако часть функций Win32 для выполнения своей задачи обращаются к нескольким функциям естественного API-ядра), кроме того, он не документирован. Поэтому, хоть приложению никто и ничто не помешает действовать в обход интерфейсов, пре-доставляемых операционными средами, и обращаться к естественному API напрямую, компания "Майкрософт" крайне не рекомендует использовать такую возможность.
Важно, чтобы пользователь понимал, где произошел сбой, чтобы потом его устранить. Если вы знаете источник ошибки, установить причину и ликвидировать ее не составит особого труда. Для примера приведу случай, произошедший со мной полгода назад. У одного моего знакомого на довольно мощной машине стояла WinXPHE. ОС я устанавливал сам, так что за ее работоспособность отвечал тоже я. Сам знакомый и вся его семья в компьютерах разбирается довольно слабо, но знаний для набора текста и работы с Интернетом хватает. Однажды мне позвонил этот товарищ и рассказал грустную историю примерно такого содержания. Установил он себе WarCraft III, начал играться, но, как только к нему приближалось вражеское войско, машина перезагружалась. Как будет рассуждать неосведомленный в архитектуре ОС пользователь: ага, машина перезагружается — значит, глючит либо игрушка (что скорее всего), либо Windows. Методы решения проблемы: переустанавливаем игру, не помогло — переустанавливаем Windows, снова не помогло — удаляем либо игру, либо Windows . А вот логическая цепочка знающего пользователя : компьютер перезагружается — значит, возникает серьезная ошибка класса STOP, что приводит к появлению BSOD, но так как в опциях системы по умолчанию стоит перезагрузка при таких ошибках, то синего экрана мы не видим. Эту версию подтверждает сообщение после сброса и запись в системном журнале. Далее: ошибки подобного рода могут возникать только в коде, работающем в режиме ядра, т.е. либо в исполнительной системе ОС (что маловероятно), либо в драйверах устройств. Информацию о сбойном драйвере можно получить в системном журнале. Я же просто просмотрел в шестнадцатеричном вьювере (Lister в Total Commander) файл дампа сбойного участка памяти (он (файл) находится в папке %SystemRoot%\Minidump), где после ключевого слова STOP и параметров ошибки были перечислены загруженные драйверы, а перед ними шел наш виновник. Им оказался драйвер интегрированной звуковой карты. Покопавшись в настройках игрушки, я обнаружил опцию Использовать 3D звук (вроде так, а может, Использовать EAX). Тут мне стала ясна вся картина происшедшего. Игра при появлении новых юнитов на горизонте пыталась сыграть их звук, используя 3D-возможности аудиокарты, но либо сама плата такими возможностями не обладает, либо они криво реализованы в плате или в драйвере — в любом случае это приводило к плачевным последствиям. Варианты решения данной проблемы: сменить драйвер или аудиокарту либо отключить 3D-звук в игре. Я как ленивый человек выбрал последний вариант. В итоге все заработало без проблем. Думаю, этот поучительный случай заставит вас логически думать при возникновении подобных проблем.
A.В XP этот процесс упрощён до предела. Больше не надо переставлять всю систему, или использовать внешние утилитки из Resource Kit-а. Ядро меняется в Device Manager -> Computer, как и любой другой драйвер. Но, это ИСКЛЮЧИТЕЛЬНО важно, НЕ СТАВЬТЕ ядро, которое не держится железом. Если не уверены, то лучше ничего не трогать, потому что последствия установки неправильного ядра непредсказуемы. Скорее всего машина просто перестанет загружаться, во всех режимах. Предотвратить подобное можно подредактировав boot.ini. Нужно всего лишь продублировать рабочий пункт меню выбора ОС, например,
multi(0)disk(0)rdisk(0)partition(1)WINDOWS="Microsoft Windows XP Professional" /fastdetect
и приписать после /fastdetect следующие опции: /kernel=ntoskchk.exe /hal=halchk.dll,
а также в директории WINDOWS\System32 сделать копии вашего ядра и HAL-а. Назвать их, конечно же, надо ntoskrnl.exe -> ntoskchk.exe и hal.dll -> halchk.dll.
Кроме этого, необходимо учитывать одну тонкость. Видимо из за того, что при установке неправильного ядра XP просто виснет, теперь весь список доступных ядер не выводиться в окне смены драйвера. Таким образом, возможна ситуация, когда точно знаете, что ядро поддерживается системой, но система не даёт его установить. В этом случае, придётся делать это вручную. Для начала найдите в windows\inf файл под названием hal.inf. После этого, изучите его, что бы выяснить, какие файлы и куда переписываются при смене ядра. Обычно перезаписывается только hal.dll, названия какого hal какому ядру соответствуют, можно узнать из списка:
Standard PC - hal.dll
Advanced Configuration and Power Interface (ACPI) PC -halacpi.dll
ACPI Uniprocessor PC - halaacpi.dll ACPI Multiprocessor PC -halmacpi.dll
Compaq SystemPro Multiprocessor or 100% Compatible - halsp.dll
MPS Uniprocessor PC -halapic.dll
MPS Multiprocessor PC -halmps
После этого остаётся "выдрать" соответствующий файл из Windows\Driver Cache\i386\driver.cab, скопировать его с Windows\system32, и сослаться на него в boot.ini.После загрузки, можно переставить его по нормальному, в списке это ядро появится.
Windows NT имеет 32-битное линейное пространство памяти (здесь "линейное" означает линейность адресов памяти, примером нелинейного адресного пространства является сегментная организация памяти Intel x86). Каждому приложению доступно собственное адресное пространство размером 4 гигабайта. Обычно, верхние два гигабайта зарезервированы для системных нужд и доступны только процессам работающим в привилегированном режиме (privileged mode). В WinNT Server 4.0 Enterprise Edition существует возможность увеличить адресное пространство доступное пользовательским приложениям путем уменьшения максимального размера памяти, отводимого ядру с 2Gb до 1.
Как нетрудно догадаться, менеджер памяти (memory manager) управляет памятью в WinNT. Физическая память разделена на блоки - страницы (pages) размером 4K для Intel, PPC и MIPS платформ и 8K для DEC Alpha. Страница является в некотором смысле атомарным объектом для менеджера памяти: все его операции над памятью сводятся к операциям над страницами.
В WinNT страницы памяти могут быть сброшены на диск (paged), при этом они помещаются в файл подкачки (page file). Однако, не каждая страница может быть сброшена на диск: в NT все системные объекты храняться в так называемых пулах (pools):
В несбрасываемом пуле храняться, например ядро системы и драйвера, если в реестре в ключе
HKLM\SYSTEM\CurrentControl\SetControl\Session\Manager\MemoryManagement параметр DisablePagingExecutive имеет значение 1. Пользовательские приложения используют обычно сбрасываемый пул.
С каждым процессом ассоциирован рабочий набор (working set) - множество страниц, находящихся в физической памяти, доступных процессу. С ростом объемы физической памяти в системе рабочие наборы также растут, а при уменьшении, соответственно, уменьшаются. Если процесс в ходе выделения памяти превысил максимальный размер рабочего набора, то его рабочий набор урезается (trim), в ходе чего наиболее "старые" страницы сбрасываются на диск.
Выделение памяти в NT аналогично UNIX. Когда процесс запрашивает память, то фактически, выделения памяти не происходит, а менеджер памяти просто резервирует какое-то количество адресов за процессом. Это множество адресов называют зарезервированной памятью (reserved memory). При попытке процесса впервые воспользоваться полученным адресным пространством, память выделяется процессу и для нее резервируется место в файле подкачки. Такая память называется выделенной (committed).
Память, которая не является выделенной или зарезервированной называется доступной памятью (available memory).
Если процесс обращается к некоторой странице и она не может быть найдена в рабочем наборе процесса, то возникает исключение сбой страницы (page fault). При этом, если нужная страница была найдена в физической памяти, то эта ситуация называется легким сбоем страницы (soft page fault). Если же нужная страница должна быть подгружена с диска, то ситуация называется тяжелым сбоем страницы (hard page fault).
Файл подкачки pagefile.sys хранит либо сброшенные страницы, либо зарезервированное место для страниц выделенной памяти. Это отличается от файла подкачки в Win9x, где при выделении памяти для нее не резервируется место в файле подкачки, и, поэтому, можно иметь файл подкачки нулевого размера.
seo & website usability | inet | html | os faq | hardware faq | memory | video | cpu | hdd | mainboard faq | printer & scaner | modem | mobiles | hackzone |
На главную | Cookie policy | Sitemap