Лабора т орн а я ра бот а 2-ОС_СП. Основные положения
Скачать 88.42 Kb.
|
Лабора т орн а я ра бот а 2АРХИТЕКТУРА WINDOWSЦельработы: изучение архитектуры операционной системы Windows. ОСНОВНЫЕ ПОЛОЖЕНИЯ Приложение (application) Windows – это совокупность исполняемых программ и вспомогательных файлов. Например, Microsoft Word представляет собой одно из популярных приложений Windows. Процессом называется исполняемый экземп- ляр приложения. Заметим, что в большинстве случаев пользователь может запускать несколько экземпляров (копий) одного и того же приложения одновременно. Каждый исполняемый экземпляр – это отдельный процесс со своей собственной обла- стью памяти. Процессом (process) называется исполняемый экземпляр (running instance) приложения и комплект ресурсов, отводя- щийся данному исполняемому приложению. Поток (thread) – это внутренняя составляющая процесса, которой операционная система выделяет процессорное время для выполнения кода. Именно потоки исполняют программный код, а не процессы. Каждый процесс должен иметь как ми- нимум один поток. Конечно, основное назначение потоков – дать процессу возможность поддерживать несколько ветвей управления, т.е. выполнять больше действий одновременно. В многопроцессорной конфигурации (компьютер с несколькими процессорами) Windows NT (но не Windows 9x) может распределять потоки по процессорам, реально обеспечивая парал- лельную обработку. В однопроцессорной конфигурации процессор должен выделять кванты времени (time slices) каждому исполняемому в данный момент потоку. Архитектура Windows NT в обобщенном виде представлена на рис. 1. Рассмотрим некоторые из изображенных пунк- тов. Режим ядра и пользовательский режимМикропроцессор Pentium имеет четыре уровня привилегий (privilege levels), известных также как кольца (rings), кото- рые управляют, например, доступом к памяти, возможностью использовать некоторые критичные команды процессора (та- кие как команды, связанные с защитой) и т.д. Каждый поток выполняется на одном из этих уровней привилегий. Кольцо 0 – наиболее привилегированный уровень, с полным доступом ко всей памяти и ко всем командам процессора. Кольцо 3 – наименее привилегированный уровень. Пользовательские приложения Системные процессы пользовательского режима Подсистема Win 32 Диспетчер виртуальной памяти Диспетчер объектов Функции библиотеки времени выполнения Диспетчер процессов и потоков
Рис. 1. Архитектура Windows NT в упрощенном виде Для обеспечения совместимости с системами на базе процессоров, отличных от тех, что выпускает компания Intel, Windows поддерживает только два уровня привилегий – кольца 0 и 3. Если поток работает в кольце 0, говорят, что он вы- полняется в режиме ядра (kernel mode). Если поток выполняется в кольце 3, говорят, что он работает в пользовательском режиме (user mode). Низкоуровневый код операционной системы действует в режиме ядра, тогда как пользовательские при- ложения выполняются, в основном, в пользовательском режиме. Прикладной поток может переключаться из пользовательского режима в режим ядра при вызове некоторых API- функций, которые требуют более высокого уровня привилегий, например, связанных с доступом к файлам или с выполнени- ем функций, ориентированных на графические операции. В действительности некоторые пользовательские потоки могут работать в режиме ядра даже больше времени, чем в пользовательском режиме. Но как только завершается выполнение той части кода, которая относится к режиму ядра, пользовательский поток ав- томатически переключается обратно в пользовательский режим. Такой подход лишает возможности писать код, предназна- ченный для работы в режиме ядра, программист может только вызывать выполняющиеся в режиме ядра системные функции (system functions). При работе с Windows NT можно определить, когда поток выполняется в пользовательском режиме, а ко- гда – в режиме ядра. Для этого используется утилита Performance Monitor (Системный монитор) из пункта Administrative Tools (Администрирование) меню Start (Пуск). Драйверы устройств работают в режиме ядра. Это обстоятельство имеет два следствия. Во-первых, в отличие от неправиль- но выполняющегося приложения неправильно работающий драйвер устройства может нарушить работу всей системы, так как он имеет доступ и ко всему системному коду, и ко всей памяти. Во-вторых, прикладной программист может получить доступ к за- щищенным ресурсам, написав драйвер псевдоустройства. СервисыТермин сервис (service) имеет в среде Windows множество значений. Некоторые из них, имеющие отношение к рас- сматриваемой теме: сервис API – функция или подпрограмма API, которая реализует некоторое действие (сервис) операционной систе- мы, такое как создание файла или работа с графикой (рисование линий или окружностей). Например, функция API CreateProcess используется в Windows для создания нового процесса; системный сервис – недокументированная функция, которая может вызываться из пользовательского режима; часто используется функциями Win32 API для предоставления низкоуровневых сервисов; внутренний (internal) сервис – функция или подпрограмма, которая может вызываться только из кода, выполняемого в режиме ядра; относится к низкоуровневой части кода Windows: к исполнительной системе Windows NT, к ядру или к слою аб- страгирования от аппаратуры (HAL). Системные процессыСистемные процессы (system processes) – это особые процессы, обслуживающие операционную систему. В системе Windows постоянно задействованы следующие системные процессы (учтите, что все они, кроме процесса system, выполня- ются в пользовательском режиме): процесс idle, который состоит из одного потока, управляющего временем простоя процессора; процесс system – специальный процесс, выполняющийся только в режиме ядра; его потоки называются системными потоками (system threads); процесс Session Manager (диспетчер сеансов) – SMSS.EXE; подсистема Win32 – CSRSS.EXE; процесс регистрации в системе – WinLogon (WINLOGON.EXE). Процесс Session Manager (SMSS.EXE) – один из первых процессов, создаваемых операционной системой в процессе загрузки. Он выполняет важные функции инициализации – такие как создание переменных окружения системы; задание имен устройств MS DOS, например, LPT1 и СОМ1; загрузка той части подсистемы Win32, которая относится к режиму ядра; запуск процесса регистрации в системе WinLogon. Процесс WinLogon управляет входом пользователей в систему и выходом из нее. Вызывается специальной комбинаци- ей клавиш Windows Ctrl+Alt+Delete. WinLogon отвечает за загрузку оболочки Windows (обычно, это Windows Explorer). Процесс system состоит из системных потоков (system threads), являющихся потоками режима ядра. Windows и многие драйверы устройств создают потоки прoцecca system для различных целей. Например, диспетчер памяти формирует систем- ные потоки для решения задач управления виртуальной памятью, диспетчер кэша использует системные потоки для управ- ления кэш-памятью, а драйвер гибкого диска – для контроля над гибкими дисками. Подсистема Win32 является разновидностью подсистемы среды (environment subsystem). Другие подсистемы среды Windows (не показаны на рисунке) включают POSIX и OS/2. POSIX является сокращением термина "переносимая операцион- ная система на базе UNIX" (portable operating system based on UNIX) и реализует ограниченную поддержку операционной системы UNIX. Назначение подсистемы среды – служить интерфейсом между пользовательскими приложениями и соответствующей частью исполнительной системы Windows. Каждая подсистема имеет свои функциональные возможности на базе единой ис- полнительной системы Windows. Любой выполняемый файл неразрывно связан с одной из этих подсистем. Подсистема Win32 содержит Win32 API в виде набора DLL – таких как KERNEL32.DLL, GDI32.DLL и USER32.DLL. В Windows NT Microsoft перенесла часть подсистемы Win32 из пользовательского режима в режим ядра. В частности, драйвер устройства режима ядра WIN32K.SYS, который управляет отображением окон, выводом на экран, вводом данных с клавиатуры или при помощи мыши и передачей сообщений. Он включает также библиотеку интерфейсов графических уст- ройств (Graphical Device Interface library – GDL.DLL), используемую для создания графических объектов и текста. Вызов Win32 API-функций. Когда приложение вызывает API-функцию из подсистемы Win32, может произойти одно из нескольких событий: если DLL подсистемы (например, USER32.DLL), экспортирующая данную API-функцию, содержит весь код, необ- ходимый для выполнения функции, то функция выполняется и возвращает результат; API-функции, вызываемой приложением, может потребоваться вызвать для выполнения вспомогательных действий дополнительный модуль, принадлежащий подсистеме Win32 (но не той DLL, которая экспортирует данную функцию); API-функции, вызываемой приложением, могут понадобиться услуги недокументированного системного сервиса. Например, чтобы создать новый процесс, API-функция CreateProcess вызывает недокументированный системный сервис NTCreateProcess для реального создания данного процесса. Это делается с помощью функций библиотеки NTDLL.DLL, ко- торая помогает осуществлять переход из пользовательского режима в режим ядра. Исполнительная система Windows. Сервисы исполнительной системы Windows составляют низкоуровневую часть Windows NT режима ядра, включенную в файл NTOSKRNL.EXE, и делятся на две группы: исполнительную систему (executive), относящуюся к верхнему уровню, и ядро (kernel). Ядро – это самый нижний уровень операционной системы, реализующий наиболее фундаментальные сервисы, такие как: планирование потоков, обработку исключений, обработку прерываний, синхронизацию процессоров в многопроцессорной системе, создание объектов ядра. Уровень абстрагирования от аппаратуры (HAL) – это библиотека режима ядра (HAL.DLL), которая реализует низ- коуровневый интерфейс с аппаратурой. Компоненты Windows и драйверы устройств от других компаний взаимодействуют с аппаратурой посредством HAL. Существует много версий HAL под различные аппаратные платформы. Подходящий уро- вень выбирается в процессе установки Windows. Объекты и их дескрипторыАрхитектура Windows базируется на использовании множества различных объектов. Объект ядра (kernel object) – это структура данных, доступ к членам которой имеет только ядро Windows. Примеры объектов ядра: объект Process представляет процесс; объект Thread определяет поток; объект File представляет открытый файл; объект File-mapping представляет отображаемый в память файл (memory-mapped file), т.е. файл, содержимое которо- го отображено непосредственно на виртуальное адресное пространство и используется как физическая память; объект Pipe используется для обмена данными между процессами; объект Event является объектом синхронизации потоков, сигнализирующим о завершении операции; объект Mutex представляет собой объект синхронизации потоков, который может использоваться несколькими про- цессами; объект Semaphore используется для того, чтобы учитывать ресурсы и сигнализировать потоку о доступности ресурса на данный момент. Кроме объектов ядра, существуют также пользовательские объекты и объекты GDI, такие как: меню, окна, шрифты, кисти и курсоры мыши. Дескрипторы. Одной из характеристик любого объекта является дескриптор, который используется для идентифика- ции этого объекта. Хотя к объектам ядра нельзя получить непосредственный доступ из пользовательского режима, в Windows API есть функции, которые можно вызывать из данного режима для управления этими объектами. Это своего рода инкапсуляция (encapsulation), защищающая объекты от непредусмотренных или неразрешенных действий. Когда создается объект ядра посредством вызова соответствующей АРI функции (CreateProcess, Greate- Thread, CreateFile и GreateFileMapping), функция возвращает дескриптор вновь созданного объекта. Такой дескриптор может быть передан другой API-функции для того, чтобы она могла управлять данным объектом. В общем, дескриптор объекта является зависимым от процесса (process-specific). Это означает, что он действует только в пределах данного процесса. Некоторые идентификаторы, такие как ID процесса, наоборот, являются идентификаторами системного уровня. Другими словами, область их действия – все процессы системы. Подсчет используемости. Объект ядра принадлежит ядру Windows, а не процессу, создавшему этот объект (или лю- бому другому процессу). Объекты могут использоваться совместно многими процессами и применяться разными способами. У каждого процесса, который работает с объектом, есть свой собственный, действующий в пределах данного процесса, деск- риптор этого объекта. С учетом этого ядро должно поддерживать подсчет используемости (usage count) каждого объекта. Ядро уничтожает объект тогда, когда его используемость становится равной нулю, но не раньше. Таким образом, процесс, создавший данный объект, может закрыть (close) его дескриптор (посредством вызова API-функции CloseHandle), но объект не будет уничто- жен, если какой-то другой процесс продолжает его использовать (имеет его дескриптор). У объектов ядра есть атрибуты за- щиты, которые можно использовать для ограничения доступа к данным объектам. Фактически это одно из основных свойств, отличающих объекты ядра от пользовательских объектов и объектов GDI. Совместное использование объектов несколькими процессами. Существует несколько способов совместного исполь- зования объекта несколькими процессами. Наследование. Когда процесс (а точнее поток этого процесса) создает объект ядра, он может указать, что дескрип- тор этого объекта наследуется (inheritable) порожденными (child) процессами, которые данный родительский процесс созда- ет впоследствии. В этой случае дескрипторы родительского и порожденного процессов одинаковы. Дублирование дескриптора. Функция DuplicateHandle определяется следующим образом: BOOL DuplicateHandle( HANDLE hSourceProcessHandle,HANDLE hSourceHandle,HANDLE hTargetProcessHandle,LPHANDLE IpTargetHandle,DWORDdwDesiredAccess,BOOLblnheriCHandle, DWORDdwOptions ); // Дескриптор процесса-источника. // Копируемый дескриптор. // Дескриптор процесса-приемника. // Указатель на дескриптор-копию. // Доступ для дескриптора-копии. // Флаг наследуемости дескриптора. // Необязательные опции. Эта функция позволяет скопировать дескриптор объекта одного процесса в другой процесс. Новый дескриптор-копия, действующий в пределах своего процесса, может иметь значение, отличное от значения дескриптора-источника, но это не существенно, так как все дескрипторы действуют только в пределах своих процессов. Именованные объекты. Многим объектам ядра при их создании может быть присвоено имя. Областью действия имени является вся система. Это означает, что любой другой процесс может получить доступ к объекту по его имени (если считать, конечно, что другому процессу это имя известно). Например, последний параметр функции HANDLECreateFileMapping( // Дескриптор отображаемого HANDLEhFile, // файла. LPSECUKITY_ATTRIBUTES // Необязательные атрибуты IpFileMappingAttributes, // защиты. DWORDflProtect, // Защита отображаемого // объекта. DWORDdwMaxiniumSizeHigh, // Старшие 32 бита размера // объекта. DWORDdwMaximumSizeLow, // Младшие 32 бита размера // объекта. LPCTSTRIpHame // Имя объекта отображения // файла. ); может использоваться для задания имени отображения файла. Предположим, создан объект File-mapping с именем MyFMO. Другой процесс может вызнать функцию OpenFileMapping с этим именем в качестве последнего аргумента. Функция вернет зависимый от процесса дескриптор объ- екта для использования во втором процессе. В виде альтернативы второй процесс может вызвать функцию GreateFileMapping, используя имя объекта в качестве ее последнего аргумента. Система определит, что объект File-mapping с таким именем уже существует и просто вернет его дескриптор. Здесь могут возникнуть проблемы, поскольку процесс счита- ет, что он создает новый объект, тогда как в действительности он получает дескриптор существующего объекта. Програм- мист должен сразу проверить возвращенное функцией CreateFileMapping значение, чтобы правильно сориентироваться в ситуации. API-функции, необходимые для отображения файлаПри выполнении данной лабораторной работы необходимо изучить и использовать следующие API-функции: Создание объекта FILE на базе существующего файла: HANDLE CreateFile(LPCTSTR lpFileName,DWORD dwDesiredAccess,DWORDdwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORDdwCreationDistribution, DWORD dwFlagsAndAttributes,HANDLEhTemplateFile ); Рассмотрим параметры этой API- функции: lpFileName – имя открываемого файла; dwDesiredAccess – GENERIC_READ, чтобы разрешить чтение с устройства. GENERIC_WRITE, чтобы разрешить запись на устройство (константы можно объединить). Ноль, чтобы разрешить только получение информации об устройстве; dwShareMode – 0 для запрета общего доступа, FILE_SHARE_READ и/или FILE_SHARE_WRITE для разрешения об- щего доступа к файлу; lpSecurityAttributes – указатель на структуру, определяющую атрибуты безопасности файла (если они поддержива- ются операционной системой); dwCreationDistribution – одна из следующих констант: CREATE_NEW: создать файл. Если файл существует, происходит ошибка; CREATE_ALWAYS: создать файл. Предыдущий файл перезаписывается; OPEN_EXISTING: открываемый файл должен существовать (обязательно используется для устройств); OPEN_ALWAYS: создать файл, если он не существует TRUNCATE_ EXISTING: существующий файл усекается до ну- левой длины; dwFlagsAndAttributes Long – комбинация следующих констант: FILE_ATTRIBUTE_ARCHIVE: установить архивный атрибут; FILEATTRIBUTE_COMPRESSED: помечает файл как подлежащий сжатию или задает сжатие для файлов каталога по умолчанию; FILE_ATTRIBUTE_NORMAL: другие атрибуты файла не заданы; FILE_ATTRJBUTE_HIDDEN: файл или каталог является скрытым; FILE_ATTRIBUTE_READONLY: файл доступен только для чтения; FILE_ATTRIBUTE_SYSTEM: файл является системным; FILE_FLAG_WRITE_THROUGH: операционная система не откладывает операции записи в файл; FILE_FLAG_OVERLAPPED: разрешить перекрывающиеся операции с файлом; FILE_FLAG_NO_BUFFERING: запретить промежуточную буферизацию файла. Адреса буферов должны выравниваться по границам секторов для текущего тома; FILE_FLAG_RANDOM_ACCESS: буферизация файла оптимизируется для произ- вольного доступа; FILE_FLAG_SEQUENTIAL_SCAN: буферизация файла оптимизируется для последовательного доступа; FILE_FLAG_DELETE_ON_CL0SE: при закрытии последнего открытого дескриптора файл удаляется. Идеально подхо- дит для временных файлов; hTemplateFile – если параметр не равен нулю, он содержит дескриптор файла, с которого будут скопированы расши- ренные атрибуты нового файла. Возвращаемое значение – дескриптор файла в случае успеха. INVALID_HANDLE_VALUE при ошибке. Устанавливает информацию GetLastError. Даже если функция завершилась успешно, но файл существовал и был задан флаг CREATE_ALWAYS или OPEN_ALWAYS, GetLast-Error возвращает ERROR_ALREADY_EXISTS. Создание объекта файлового отображения File-mapping: HANDLECreateFileMapping(HANDLEhFile, LPSECURITY_ATTRIBUTESlpFileMappingAttributes,DWORDflProtect, DWORD dwMaximumSizeHigh,DWORD dwMaximumSizeLow,LPCTSTRlpName ); Рассмотрим параметры этой API- функции: hFile – дескриптор файла, для которого создается отображение; lpFileMappingAttributes – SECUR1TY_ATTRIBLITES – объект безопасности, используемый при создании файлового отображения. NULL для использования стандартных атрибутов безопасности; flProtect – одна из следующих констант: PAGE_READONLY: созданное файловое отображение доступно только для чтения; PAGE_READWRITE: файловое отображение доступно для чтения и записи; PAGE_WRITECQPY: разрешается копирование при записи; также в комбинацию могут включаться следующие кон- станты: SЕС_СОММГГ: для страниц секции выделяется физическое место в памяти или файле подкачки; SEC_IMAGE: файл является исполняемым; SEC_RESERVE: для страниц секции резервируется виртуальная память без фактического выделения. dwMaximumSizeHigh – максимальный размер файлового отображения (старшие 32 бита); dwMaximumSizeLow – максимальный размер файлового отображения (младшие 32 бита); Если параметры dwMaxi- mumSizeHigh и dwMaximumSizeLow одновременно равны нулю, используется фактический размер файла на диске; lpName – имя объекта файлового отображения. Если файловое отображение с заданным именем уже существует, функция открывает его. Возвращаемое значение – дескриптор созданного объекта файлового отображения. Ноль в случае ошибки. Устанавли- вает информацию GetLast-Error. Даже если функция завершилась успешно, но возвращенный манипулятор принадлежит существующему объекту фазового отображения, GetLastError возвращает ERROR_ALREADY_EXISTS. В этом случае раз- мер файлового отображении определяется размером существующего объекта, а не параметрами функции. Функция отображает объект файлового отображения в адресное пространство текущего процесса: LPVOID MapViewOfFile(HANDLE hFileMappingObject,DWORD dwDesiredAccess,DWORD dwFileOffsetHigh,DWORD dwFileOffsetLow,DWORDdwNumberOfBytesToMap ); Рассмотрим параметры этой API- функции: hFileMappingObject – дескриптор объекта файлового отображения; dwDesiredAccess – одна из следующих констант: FILE_MAP_WRITE: отображение доступно для чтения и записи. Объект файлового отображения должен быть создан с флагом PAGE_READWRITE; FILE_MAP_READ: отображение доступно только для чтения. Объект файлового отображения должен быть создан с флагом PAGE_READ или PAGE_READWRITE; FILE_MAP_ALL_ACCESS: то же, что FILE_MAP_WRITE HLE_MAP_COPY: ко- пирование при записи. В Windows 95 Обьект файлового отображения должен быть создан c флагом PAGE_WRITECOPY; dwFileOffsetHigh – старшие 32 бита смещения в файле, с которого начинается отображение; dwFileOffsetLow – младшие 32 бита смещения в файле, с которого начинается отображение; dwNumberOfBytesToMap – количество отображаемых байт в файле. Ноль, чтобы использовать весь объект файлово- го отображения. Возвращаемое значение – начальный адрес отображения в памяти. Ноль при ошибке. Устанавливает информацию GetLastError. Комментарии: dwOffsetLow и dwOffsetHigh должны содержать смещение с учетом гранулярности выделения памяти в системе. Другими словами, если гранулярность памяти в системе равна 64 Кбайт (выделяемые блоки выравниваются по гра- нице 64 Кбайт), значение должно быть кратно 64 Кбайт. Чтобы получить гранулярность выделения памяти в системе, вос- пользуйтесь функцией GetSystemlnfo. В большинстве приложений передается ноль, чтобы отображение начиналось с начала файла. Параметр IpBaseAddress также должен быть кратен значению гранулярности. Функция закрывает объект ядра. К числу объектов ядра относятся объекты файлов, файловых отображений, процес- сов, потоков, безопасности и синхронизации: BOOLCloseHandle( HANDLEhObject // Дескриптор закрываемого объекта. ); Возвращаемое значение – ненулевое значение в случае успеха, ноль при ошибке. Устанавливает информацию GetLastError. Объекты ядра удаляются лишь после того, как будут закрыты все ссылки на них. Функция прекращает отображение объекта в адресное пространство текущего процесса: BOOLUnmapViewOfFile( LPCVOIDlpBaseAddress // Базовый адрес отображения, // установленного ранее функцией // MapViewOfFile. ); ЗАДАНИЕ ДЛЯ ВЫПОЛНЕНИЯ ЛАБОРАТОРНОЙ РАБОТЫ Разработать программу, реализующую следующую задачу: Создать текстовый файл (можно с использованием notepad). Создасть объект File на базе созданного в предыдущем пункте файла, используя АРI-функцию CreateFile. Вывести значение дескриптора объекта File. Используя дескриптор объекта File-mapping, а также API-функцию MapViewOf File, отобразить части файла в память. Данная функция назначает область виртуальной памяти, выделяемой этому файлу. Базовый адрес выделенной об- ласти памяти является дескриптором представления этой области в виде отображения файла. Используя базовый адрес и функцию CopyMemory, прочитайте информацию из отображаемого файла. Измените регистр текста в тестовом файле, и запишите информацию в этот же файл. Закрыть все дескрипторы. На экране должны фиксироваться все этапы работы созданного приложения. КОНТРОЛЬНЫЕ ВОПРОСЫ Что такое режим ядра и пользовательский режим? Перечислите объекты ядра ОС. Понятие сервиса ОС. Какие системные процессы вы знаете? Опишите работу ядра ОС в привилегированном режиме. Какие API-функции необходимы для отображения файла в адресное пространство? Какая API-функция возвращает начальный адрес области отражения файла? |