Системный объект в windows управляющий диспетчеризацией и синхронизацией

Обновлено: 07.07.2024

С помощью одного экземпляра примитива синхронизации можно обеспечить защиту при обращении к общему ресурсу. Если для защиты одного и того же ресурса используются разные экземпляры примитива синхронизации, то защита, предоставляемая примитивом синхронизации, будет обходиться.

Класс WaitHandle и типы упрощенной синхронизации

    , который предоставляет монопольный доступ к общему ресурсу. Если мьютексом не владеет ни один поток, сообщается состояние мьютекса. , ограничивающий число потоков, которые могут одновременно обращаться к ресурсу или пулу ресурсов. Состояние семафора становится сигнальным, когда это число становится больше нуля, и несигнальным, когда равно нулю. , который представляет событие синхронизации потоков и может быть в сигнальном или несигнальном состоянии. , который является производным от EventWaitHandle и при получении сигнала автоматически сбрасывается в сигнальное состояние после освобождения одиночного потока в состоянии ожидания. , который является производным от EventWaitHandle и при получении сигнала остается в сигнальном состоянии до вызова метода Reset.

Дополнительные сведения см. в справочной документации по API WaitHandle.

Типы упрощенной синхронизации не основаны на дескрипторах базовой операционной системы и обычно обеспечивают лучшее быстродействие. Тем не менее они не могут использоваться для внутрипроцессной синхронизации. Эти типы можно использовать для синхронизации потоков в одном приложении.

Некоторые из них являются альтернативой типам, производным от WaitHandle. Например, SemaphoreSlim является упрощенной альтернативой Semaphore.

Синхронизация доступа к общему ресурсу

Monitor класс

Класс System.Threading.Monitor предоставляет монопольный доступ к общему ресурсу, блокируя или разблокируя объект, определяющий ресурс. Во время блокировки поток, удерживающий блокировку, может снова поставить и снять блокировку. Любой другой поток не может получить блокировку, и метод Monitor.Enter ожидает снятия блокировки. Метод Enter получает снятую блокировку. Можно также использовать метод Monitor.TryEnter, чтобы задать количество времени, в течение которого поток пытается получить блокировку. Так как класс Monitor реализует привязку потока, поток, который получил блокировку, должен снять ее, вызвав метод Monitor.Exit.

Можно координировать взаимодействие потоков, которые получают блокировку для одного и того же объекта, с помощью методов Monitor.Wait, Monitor.Pulse и Monitor.PulseAll.

Дополнительные сведения см. в справочной документации по API Monitor.

Mutex класс

Класс System.Threading.Mutex, как и Monitor, предоставляет монопольный доступ к общему ресурсу. С помощью вызова одной из перегрузок метода Mutex.WaitOne можно запросить владение мьютексом. Как и Monitor, Mutexреализует привязку потока, и поток, который получил мьютекс, должен освободить его, вызвав метод Mutex.ReleaseMutex.

В отличие от Monitor, класс Mutex может использоваться для межпроцессной синхронизации. Для этого нужно использовать именованный мьютекс, который виден в операционной системе. Чтобы создать экземпляр именованного мьютекса, используйте конструктор Mutex, который задает имя. Также можно вызвать метод Mutex.OpenExisting, чтобы открыть существующий именованный системный мьютекс.

Дополнительные сведения см. в статье о мьютексах и справочной документации по API Mutex.

Структура SpinLock

Структура System.Threading.SpinLock, как и Monitor, предоставляет монопольный доступ к общему ресурсу на основе доступности блокировки. Когда SpinLock пытается получить блокировку, которая недоступна, этот примитив будет ожидать в цикле, постоянно проверяя возможность получения блокировки.

Дополнительные сведения о преимуществах и недостатках использования SpinLock см. в статье о SpinLock и справочной документации по API SpinLock.

Класс ReaderWriterLockSlim

Класс System.Threading.ReaderWriterLockSlim предоставляет монопольный доступ к общему ресурсу для записи и обеспечивает одновременный доступ к ресурсу для чтения нескольким потокам. Можно использовать ReaderWriterLockSlim для синхронизации доступа к общей структуре данных, поддерживающей потокобезопасные операции чтения, но требующей монопольного доступа для выполнения операции записи. Если поток запрашивает монопольный доступ (например, путем вызова метода ReaderWriterLockSlim.EnterWriteLock), последующие запросы модуля чтения и записи блокируются, пока все существующие модули чтения не освободят блокировку, а модуль записи не получит и не снимет блокировку.

Дополнительные сведения см. в справочной документации по API ReaderWriterLockSlim.

Классы Semaphore и SemaphoreSlim

Классы System.Threading.Semaphore и System.Threading.SemaphoreSlim ограничивают число потоков, которые могут одновременно обращаться к ресурсу или пулу ресурсов. Дополнительные потоки, запрашивающие ресурс, ожидают освобождения семафора любым из потоков. Так как семафор не реализует привязку потока, поток может занять семафор, а другой поток может его освободить.

SemaphoreSlim — это упрощенная альтернатива Semaphore, которую можно использовать для синхронизации в рамках одного процесса.

В Windows можно использовать Semaphore для внутрипроцессной синхронизации. Для этого необходимо создать экземпляр Semaphore, выполняющий роль именованного системного семафора. Это можно сделать с помощью конструкторов Semaphore, которые задают имя или метод Semaphore.OpenExisting. SemaphoreSlim не поддерживает именованные системные семафоры.

Дополнительные сведения см. в статье о классах Semaphore и SemaphoreSlim и справочной документации по API Semaphore или SemaphoreSlim.

Взаимодействие потоков или сигнализация

Взаимодействие потоков (или сигнализация потоков) означает, что поток должен ждать уведомления или сигнала от одного или нескольких потоков, чтобы продолжить. Например, если поток A вызывает метод Thread.Join потока B, поток А блокируется до завершения потока B. Примитивы синхронизации, описанные в предыдущем разделе, реализуют другой механизм сигнализации: снятие блокировки потоком является сигналом другому потоку о возможности продолжать исполнение, получив блокировку.

Классы EventWaitHandle, AutoResetEvent и ManualResetEvent

Класс System.Threading.EventWaitHandle представляет событие синхронизации потока.

Событие синхронизации может находиться в сигнальном или несигнальном состоянии. Если состояние события несигнальное, поток, который вызывает перегрузку события WaitOne, будет заблокирован, пока состояние события не станет сигнальным. Метод EventWaitHandle.Set задает сигнальное состояние события.

Поведение EventWaitHandle после получения сигнала зависит от его режима сброса:

    , созданный с помощью флага EventResetMode.AutoReset, автоматически сбрасывается после освобождения одного потока в состоянии ожидания. Это похоже на турникет, пропускающий только один поток каждый раз, когда он переводится в сигнальное состояние. Такое поведение характерно для класса System.Threading.AutoResetEvent, наследующего EventWaitHandle. , созданный с помощью флага EventResetMode.ManualReset, находится в сигнальном состоянии, пока не будет вызван его метод Reset. Это как ворота, которые закрыты до получения сигнала и остающиеся затем открытыми, пока кто-нибудь их не закроет. Такое поведение характерно для класса System.Threading.ManualResetEvent, наследующего EventWaitHandle. Класс System.Threading.ManualResetEventSlim является упрощенной альтернативой ManualResetEvent.

В Windows можно использовать EventWaitHandle для синхронизации между процессами. Для этого необходимо создать экземпляр EventWaitHandle, выполняющий роль именованного системного события синхронизации. Это можно сделать с помощью конструкторов EventWaitHandle, которые задают имя или метод EventWaitHandle.OpenExisting.

Дополнительные сведения см. в статье о EventWaitHandle. Справочные сведения об API см. здесь: EventWaitHandle, AutoResetEvent, ManualResetEvent и ManualResetEventSlim.

Класс CountdownEvent

Класс System.Threading.CountdownEvent представляет событие, возникающее, когда его счетчик имеет значение ноль. Когда CountdownEvent.CurrentCount не равен нулю, поток, который вызывает CountdownEvent.Wait, блокируется. Вызовите CountdownEvent.Signal, чтобы уменьшить значение счетчика события.

В отличие от ManualResetEvent или ManualResetEventSlim, которые позволяют разблокировать несколько потоков с помощью сигнала от одного потока, CountdownEvent может разблокировать один или несколько потоков с помощью сигналов от нескольких потоков.

Дополнительные сведения см. в статье о CountdownEvent и справочной документации по API CountdownEvent.

Класс Barrier

Класс System.Threading.Barrier представляет барьер выполнения потоков. Поток, который вызывает метод Barrier.SignalAndWait, сообщает, что он достиг барьера и ожидает, пока другие участвующие потоки не достигнут барьера. Когда все участвующие потоки достигают барьера, их выполнение продолжается, а барьер сбрасывается и может использоваться повторно.

Можно использовать Barrier, если одному или нескольким потокам требуются результаты других потоков для перехода к следующему этапу вычисления.

Дополнительные сведения см. в статье о Barrier и справочной документации по API Barrier.

Interlocked класс

Класс System.Threading.Interlocked предоставляет статические методы, которые выполняют простые атомарные операции над переменной. К этим атомарным операциям относится добавление, инкремент и декремент, обмен и условный обмен, зависящий от сравнения, а также операция чтения 64-разрядного целого числа.

Дополнительные сведения см. в справочной документации по API Interlocked.

Структура SpinWait

Структура System.Threading.SpinWait обеспечивает поддержку ожидания спин-блокировки. Ее можно использовать, когда потоку нужно дождаться возникновения события или выполнения условия, но фактическое время ожидания будет меньше периода, требуемого для применения дескриптора ожидания или других способов блокировки потока. Используя SpinWait, можно задать короткий интервал времени для цикла ожидания, а затем вернуть управление (например, с помощью ожидания или спящего режима), только если условие не было выполнено в течение заданного времени.

Дополнительные сведения см. в статье о SpinWait и справочной документации по API SpinWait.

Над executive надстраиваются процессы пользовательского режима, обеспечивающие исполнение программ, разработанных для других ОС.

Windows 2000 использует подсистему Win32 как основное операционное окружение. Подсистема Win32 используется для запуска всех процессов. Она же обеспечивает средства работы с мышью, клавиатурой и средства графики.

Окружение MS-DOS обеспечивается приложением Win32 , называемым Virtual Dos machine (VDM),процессом пользовательского уровня, для которого поддерживается страничная организация и диспетчеризация, как и для всех других потоков.

Окружение для 16-битовых Windows обеспечивается VDM , которая содержит подсистему Windows on Windows. Последняя предоставляет процедуры ядра Windows 3.1 для менеджера окон и функций GDI .

Подсистема POSIX спроектирована для исполнения POSIX -приложений, следующих POSIX .1 – стандарту, который базируется на модели UNIX .

Подсистема OS/2 выполняет OS/2 - приложения.

Подсистема входа и безопасности аутентифицирует пользователей, входящих в систему Windows 2000 . Требуется, чтобы пользователи имели учетную запись с логином и пароль . Пакет аутентификации подсистемы безопасности аутентифицирует всех пользователей, которые пытаются осуществить доступ к какому-либо объекту системы. Windows 2000 использует Kerberos как пакет аутентификации по умолчанию.

Ключевые термины

Plug-and-Play (PnP) – механизм автоматического распознавания изменений в конфигурации оборудования и адаптации к ним (установки соответствующих драйверов).

Virtual Dos Machine (VDM) - процесс пользовательского уровня, обеспечивающий совместимость с приложениями MS-DOS .

Блокировщик (spin lock, буквально – вертящийся замок ) – системный механизм синхронизации , используемый для взаимного исключения процессов ядра Windows .

Исполнительная подсистема (executive) – основная часть ядра Windows , исполняемая в защищенном режиме, реализующая базовые системные сервисы .

Локальный вызов процедуры (LPC) – системный механизм вызова процедур Windows , передающий запросы и результаты между клиентским и серверным процессами на локальной машине; используется для запросов к сервисам различных подсистем ОС.

Объект-диспетчер - системный объект в Windows , управляющий диспетчеризацией и синхронизацией.

Объектная ссылка (object handle) - ссылка на системный объект ядра Windows .

Управляющий объект - системный объект Windows , управляющий асинхронным вызовом процедуры, обработкой прерывания, нотификацией об электропитании или профилированием .

Уровень абстрагирования от аппаратуры (hardware abstraction layer, HAL) – динамически линкуемая библиотека Windows , инкапсулирующая код, зависящий от конкретного процессора, - тем самым обеспечивающая независимость от аппаратуры всего остального кода Windows .

Краткие итоги

Windows 2000 / XP / 2003 / 2008 / 7 – новейшая линия в развитии ОС Windows , которой предшествовало более чем 20-летнее развитие Windows от графической оболочки в среде MS DOS до наиболее популярной в мире операционной системы. Windows 2000 – объектно-ориентированная ОС, основными целями разработки которой являются переносимость , безопасность , соответствие POSIX , поддержка многопроцессорности , расширяемость , поддержка интернационализации , совместимость приложений с MS DOS и первыми версиями Windows . Использует архитектуру микроядра.

Первой ОС в новой линии развития Windows стала Windows NT, выпущенная в середине 1990-х гг. Windows NT, 2000 и более новые версии Windows имеют общую кодовую базу – ядро ОС.

Windows 2000 написана на C и C++. Код, зависящий от процессора, выделен в специальный API – hardware abstraction layer ( HAL ).

Архитектура Windows 2000 - многоуровневая. В защищенном режиме исполняется ядро , исполнительная подсистема ядра – executive , реализующая базовые системные сервисы , и HAL . Над этими компонентами надстраиваются подсистемы пользовательского режима, эмулирующие различные ОС и обеспечивающие реализацию безопасности.

Ядро Windows разработано в объектно-ориентированном стиле и использует два набора системных объектов – объекты-диспетчеры и управляющие объекты.

Ядро поддерживает процессы и потоки. Используется гибкая система приоритетов, включающая поддержку потоков реального времени и разделения времени. Процессы реального времени планируются как soft real-time (без обязательности выдерживания фиксированного интервала времени ответа).

Ядро обеспечивает обработку прерываний и системный механизм исключений. Для синхронизации процессов ядра используются блокировщики типа spin locks.

Менеджер системных объектов обеспечивает генерацию системных объектных ссылок ( object handles) и выполнение базовых операций над объектами. Поддерживается именование объектов и объекты – символические ссылки . Каждый объект защищен списком управления доступом .

Для реализации виртуальной памяти используется двухуровневая таблица страниц с размером страницы 4 килобайта . Используются файлы откачки.

Менеджер ввода-вывода поддерживает синхронные и асинхронные операции , тайм-ауты для драйверов, кэширование ввода-вывода, использование файлов, отображаемых в память .

Монитор безопасности использует маркеры безопасности процессов и списки управления доступом к объектам для авторизации.

Менеджер PnP отслеживает изменения в конфигурации и установку соответствующих драйверов новых устройств.

Подсистемы окружения Windows : подсистема Win32 ; DOS Virtual Machine ; подсистема Windows on Windows ( исполнение 16-битовых приложений Windows ); подсистема POSIX , подсистема OS/2 ; подсистема входа и безопасности (управляет учетными записями пользователей, используя Kerberos -аутентификацию по умолчанию).

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

Сложность проблемы организации взаимодействия параллельных процессов существенно разная для систем, использующих вытесняющую и невытесняющую диспетчеризацию процессов. При вытесняющей диспетчеризации процесс может быть прерван диспетчером практически в любой момент. Помимо задачи сохранения и последующего восстановления контекста процесса (см. п. 4.2.5), которая должна решаться самой ОС, возникают еще и задачи обеспечения взаимного исключения при выполнении критических секций в многозадачных приложениях. Только разработчик программы может решить, какие части текста его программы являются критическими секциями и должны быть защищены семафорами.

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

Все версии Windows от 1.0 до 3.11 представляли собой достаточно мощные многозадачные системы с невытесняющей диспетчеризацией. Версии, начиная с Windows NT и Windows 95, используют вытесняющую диспетчеризацию.

Понятие объекта в Windows

В ОС Windows широко используется понятие системного объекта. По сути, любой объект представляет собой некоторую структуру данных, расположенную в адресном пространстве системы. Поскольку приложения не могут иметь доступа к этой памяти, то для работы с объектом приложение должно получить хэндл объекта – некоторое условное число, которое будет представлять данный объект при обращении к API-функциям. Процесс получает хэндл, как правило, при вызове функции CreateXxx (здесь Xxx – название объекта), которая может либо создать новый объект, либо открыть существующий объект, созданный другим процессом. Функции вида OpenXxx позволяют только открыть существующий объект.

Объекты Windows делятся на объекты ядра (KERNEL), позволяющие управлять процессами, объекты USER, описывающие работу с окнами, и объекты GDI, задающие графические ресурсы Windows. В данном курсе рассматриваются только объекты ядра. Процессы, нити и открытые файлы являются примерами объектов ядра.

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

Хэндл объекта может быть использован только тем процессом, который создал или открыл этот объект. Нельзя просто переслать значение хэндла другому процессу, оно не будет действовать в другом контексте. Имеется, однако, функция DuplicateHandle, которая создает корректную копию хэндла, требуя указать для этого, какой процесс создает копию, какого именно хэндла и для какого процесса предназначена копия.

Если хэндл объекта больше не нужен данному процессу, его следует закрыть с помощью функции CloseHandle, общей для разных типов объектов.

Объект существует до тех пор, пока не будут закрыты все хэндлы, указывающие на него.

Процессы и нити

Процесс создается при запуске программы (EXE-файла). Одновременно создается одна нить процесса (должен же кто-то работать!). Создание процесса выполняется с помощью API-функции CreateProcess. Основными параметрами при вызове этой функции являются следующие.

· Имя файла запускаемой программы.

· Командная строка, передаваемая процессу при запуске.

· Атрибуты защиты для создаваемых процесса и нити. И процесс, и нить являются объектами ядра Windows и в этом качестве могут быть защищены от несанкционированного доступа (например, от попыток других процессов вмешаться в работу данного процесса).

· Различные флаги, уточняющие режим создания процесса. Среди них следует отметить класс приоритета процесса, флаг отладочного режима (при этом система будет уведомлять процесс-родитель о действиях порожденного процесса), а также флаг создания приостановленного процесса, который не начнет работать, пока не будет вызвана функция возобновления работы.

· Блок среды процесса.

· Текущий каталог процесса.

· Параметры первого окна, которое будет открыто при запуске процесса.

· Адрес блока информации, через который функция возвращает родительскому процессу четыре числа: идентификатор созданного процесса, идентификатор нити, хэндл процесса и хэндл нити.

Если процесс успешно создан, функция CreateProcess возвращает ненулевое значение.

Класс приоритета процесса используется при определении приоритетов его нитей. Подробнее об этом в п. 4.5.3.

Хэндл объекта ядра Windows (в данном случае процесса или нити) позволяет выполнять различные операции с этим объектом. Подробнее о хэндлах и идентификаторах см. п. 4.5.4.

После создания процесса его единственная нить начинает выполнять программу процесса, работая параллельно с нитями других запущенных процессов. Если логика работы программы предполагает параллельное выполнение каких-либо действий в рамках одного процесса, то могут быть созданы дополнительные нити. Для этого используется функция CreateThread. Ее основные параметры следующие:

· атрибуты защиты для создаваемой нити;

· размер стека нити;

· стартовый адрес нити (обычно нить связывается с выполнением одной из функций, описанных в программе процесса, при этом в качестве стартового адреса указывается имя функции);

· параметр-указатель, позволяющий передать нити при запуске некоторое значение в качестве аргумента;

· флаг создания нити в приостановленном состоянии;

· указатель на переменную, в которой функция должна возвратить идентификатор созданной нити.

Возвращаемым значением функции CreateThread является хэндл созданной нити либо NULL, если создать нить не удалось.

Прекрасным примером многонитевой программы является Microsoft Word. В то время как основная нить обрабатывает ввод с клавиатуры, отдельная нить может динамически рассчитывать разбиение текста на страницы, еще одна нить может в это же время выполнять печать документа или его сохранение.

Для завершения работы нити используется вызов функции ExitThread. Для завершения работы всего процесса любая из его нитей может вызвать функцию ExitProcess. Единственным параметром каждой из этих функций является код завершения нити или процесса.

Завершение процесса приводит к освобождению всех ресурсов, которыми владел процесс: памяти, открытых файлов и т.п.

При завершении процесса завершаются все его нити. И наоборот, при завершении последней нити процесса завершается и сам процесс.

Не слишком широко известно, что нить не является самой мелкой единицей организации вычислений. На самом деле Windows позволяет создать внутри нити несколько волокон (fiber), которые в обычной терминологии могут быть описаны как сопрограммы или как задачи с невытесняющей диспетчеризацией, работающие в рамках одной и той же задачи с вытесняющей диспетчеризацией. Переключение волокон выполняется только явно, с помощью функции SwitchToFiber. Об использовании сопрограмм см. /15/.

Планировщик Windows

Задачей планировщика является выбор очередной нити для выполнения. Планировщик вызывается в трех случаях:

· если истекает квант времени, выделенный текущей нити;

· если текущая нить вызвала блокирующую функцию (например, WaitForMultipleObjects или ReadFile) и перешла в состояние ожидания;

· если нить с более высоким приоритетом пробудилась от ожидания или была только что запущена.

Для выбора нити используется алгоритм приоритетной очереди. Для каждого уровня приоритета система ведет очередь активных нитей (т.е. нитей, находящихся в состоянии готовности). Для выполнения выбирается очередная нить из непустой очереди с самым высоким приоритетом.

Очереди активных нитей пополняются за счет нитей, проснувшихся после состояния ожидания и нитей, вытесненных планировщиком. Как правило, нить помещается в конец очереди. Исключение делается для нити, вытесненной до истечения ее кванта времени более приоритетной нитью. Такая «обиженная» нить ставится в голову очереди.

Значение кванта времени для серверных установок Windows равно обычно 120 мс, для рабочих станций – 20 мс.

Как вы думаете, почему для серверов квант времени больше?

Теперь подробнее о приоритетах. Хотя общая схема их назначения одинакова для всех версий Windows, детали могут разниться. Дальнейшее изложение ориентировано на Windows NT 4.0.

Все уровни приоритета нитей пронумерованы от 0 (самый низкий приоритет) до 31 (самый высокий). Уровни от 16 до 31 называются приоритетами реального времени, они предназначены для выполнения критичных по времени системных операций. Только сама система или пользователь с правами администратора могут использовать приоритеты из этой группы. Уровни от 0 до 15 называются динамическими приоритетами.

В Windows используется двухступенчатая схема назначения приоритетов. При создании процесса ему назначается (а впоследствии может быть изменен самой программой или пользователем) один из четырех классов приоритета, с каждым из которых связано базовое значение приоритета:

· Realtime (базовый приоритет 24) – высший класс приоритета, допустимый только для системных процессов, занимающих процессор на очень короткое время;

· High (базовый приоритет 13) – класс высокоприоритетных процессов;

· Normal (базовый приоритет 8) – обычный класс приоритета, к которому относится большая часть запускаемых прикладных процессов;

· Idle (базовый приоритет 4) – низший (буквально – «холостой» или «простаивающий») класс приоритета, характерный для экранных заставок, мониторов производительности и других программ, которые не должны мешать жить более важным программам.

Собственно приоритет связывается не с процессом, а с каждой его нитью. Приоритет нити определяется базовым приоритетом процесса, к которому прибавляется относительный приоритет нити – величина от –2 до +2. Относительный приоритет назначается нити при ее создании и может при необходимости изменяться. Имеется также возможность назначить нити критический приоритет (31 для процессов реального времени, 15 для остальных) или холостой приоритет (16 для процессов реального времени, 0 для остальных).

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

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

· Когда заблокированная нить дождалась нужного ей события, к приоритету нити прибавляется величина, зависящая от причины ожидания. Эта прибавка может достигать 6 единиц (но приоритет не должен превысить 15), если нить разблокирована вследствие нажатия клавиши или кнопки мыши. Таким способом система стремится уменьшить время реакции на действия пользователя. Всякий раз, когда нить полностью использует свой квант времени, прибавка уменьшается на 1, пока приоритет нити не вернется к своему заданному значению.

· Если нить владеет окном переднего плана (т.е. тем, с которым работает пользователь), то ради уменьшения времени реакции планировщик может увеличить квант времени для этой нити с 20 мс до 40 или 60 мс, в зависимости от настроек системы.

· Если планировщик обнаруживает, что некоторая нить пребывает в очереди более 3 с, то он повышает ее приоритет аж до 15 и удваивает ее квант. Но эта благотворительность разовая: когда Золушка-нить израсходует увеличенный квант или заблокируется, ее приоритет и квант возвращаются к прежним значениям. Смысл акции понятен: система пытается обеспечить хоть какое-то продвижение даже для низкоприоритетных нитей.

Процесс и нить как объекты

Подсистема управления процессами в Windows позволяет рассматривать процессы и нити как объекты, над которыми нити различных процессов могут выполнить целый ряд действий. Для этого требуется иметь хэндл процесса или нити. Как нам известно, такие хэндлы возвращаются как побочные результаты работы функций CreateProcess и CreateThread. Это позволяет процессу, запустившему другой процесс или нить, выполнять с ними необходимые действия. Однако в некоторых случаях желательно дать возможность управлять процессом не процессу-«родителю», а другому, совершенно постороннему процессу (например, программе администрирования системы). Проблема при этом в том, что, как уже отмечалось, хэндл в Windows имеет смысл только в пределах того процесса, который вызвал функцию Create и не может быть просто передан другому процессу.

Функция OpenProcess позволяет одному процессу получить хэндл любого другого процесса, указав для этого два параметра: идентификатор интересующего процесса и маску, задающую набор запрашиваемых прав по отношению к этому процессу. Если подсистема безопасности Windows, сверив маркер доступа запрашивающего процесса с дескриптором безопасности процесса-объекта (см. п. 3.8.4.1), сочтет запрос законным, то функция вернет требуемый хэндл.

А о каких, собственно, правах идет речь? Что именно один процесс может сделать с другим процессом? Основные права следующие:

· запускать новую нить процесса;

· запрашивать и изменять класс приоритета процесса;

· читать и записывать данные в памяти процесса;

· использовать процесс в качестве объекта синхронизации;

· принудительно прекращать выполнение процесса;

· запрашивать код завершения процесса.

Все перечисленные действия выполняются с помощью соответствующих API-функций (например, для прекращения процесса вызывается функция TerminateProcess), одним из параметров которых указывается хэндл открытого процесса-объекта.

Синхронизация нитей

Способы синхронизации

Windows предоставляет разнообразные возможности для синхронизации работы нитей, т.е., иначе говоря, для организации пассивного ожидания нитью некоторых событий, связанных с работой других нитей того же процесса или других процессов.

· Разнообразные условия ожидания могут быть реализованы с помощью объектов синхронизации и функций ожидания, которые позволяют заблокировать нить до момента перехода указанного объекта в сигнальное состояние.

· Использование переменных типа CRITICAL_SECTION, в отличие от предыдущих способов, возможно только для синхронизации нитей одного и того же процесса, но зато реализуется более эффективно по времени и памяти.

Над executive надстраиваются процессы пользовательского режима, обеспечивающие исполнение программ, разработанных для других ОС.

Windows 2000 используетподсистему Win32 как основное операционное окружение. Подсистема Win32используетсядля запуска всех процессов. Она же обеспечивает средства работы с мышью, клавиатурой исредстваграфики.

Окружение MS-DOS обеспечивается приложением Win32, называемымVirtual Dos machine (VDM), процессом пользовательского уровня, для которого поддерживается страничная организация и диспетчеризация, как и для всех других потоков.

Окружение для 16-битовых Windows обеспечивается VDM, которая содержит подсистемуWindows on Windows. Последняя предоставляет процедуры ядра Windows 3.1 для менеджера окон и функций GDI.

Подсистема POSIX спроектирована для исполнения POSIX-приложений, следующих POSIX.1 – стандарту, который базируется на модели UNIX.

Подсистема OS/2 выполняет OS/2 - приложения.

Подсистема входа и безопасности аутентифицирует пользователей, входящих в систему Windows 2000. Требуется, чтобы пользователи имели учетную запись с логином и пароль. Пакет аутентификации подсистемы безопасности аутентифицирует всех пользователей, которые пытаются осуществить доступ к какому-либо объекту системы. Windows 2000 используетKerberos как пакет аутентификации по умолчанию.

Ключевые термины

Plug-and-Play (PnP) – механизм автоматического распознавания изменений в конфигурации оборудования и адаптации к ним (установки соответствующих драйверов).

Virtual Dos Machine (VDM) - процесс пользовательского уровня, обеспечивающий совместимость с приложениями MS-DOS.

Блокировщик (spin lock, буквально – вертящийся замок) – системный механизм синхронизации,используемыйдля взаимного исключения процессов ядра Windows.

Исполнительная подсистема (executive) – основная часть ядра Windows, исполняемая в защищенном режиме, реализующая базовые системные сервисы.

Локальный вызов процедуры (LPC) – системный механизм вызова процедур Windows, передающий запросы и результаты междуклиентскими серверным процессами на локальной машине; используется для запросов к сервисам различных подсистем ОС.

Объект-диспетчер - системный объект в Windows, управляющий диспетчеризацией и синхронизацией.

Объектная ссылка (object handle) - ссылка на системный объект ядра Windows.

Управляющий объект - системный объект Windows, управляющий асинхронным вызовом процедуры, обработкой прерывания, нотификацией об электропитании или профилированием.

Уровень абстрагирования от аппаратуры (hardware abstraction layer, HAL) – динамически линкуемая библиотека Windows, инкапсулирующая код, зависящий от конкретного процессора, - тем самым обеспечивающая независимость от аппаратуры всего остального кода Windows.

Краткие итоги

Windows 2000 / XP / 2003 / 2008 / 7 – новейшая линия в развитии ОС Windows, которой предшествовало более чем 20-летнее развитие Windows от графической оболочки в среде MS DOS до наиболее популярной в мире операционной системы. Windows 2000 – объектно-ориентированная ОС, основными целями разработки которой являются переносимость, безопасность, соответствие POSIX, поддержка многопроцессорности, расширяемость, поддержка интернационализации, совместимость приложений с MS DOS и первыми версиями Windows. Использует архитектуру микроядра.

Первой ОС в новой линии развития Windows стала Windows NT, выпущенная в середине 1990-х гг. Windows NT, 2000 и более новые версии Windows имеют общую кодовую базу – ядро ОС.

Windows 2000 написана на C и C++. Код, зависящий от процессора, выделен в специальный API – hardware abstraction layer (HAL).

Архитектура Windows 2000 - многоуровневая. В защищенном режиме исполняется ядро, исполнительная подсистема ядра – executive, реализующая базовые системные сервисы, и HAL. Над этими компонентами надстраиваются подсистемы пользовательского режима, эмулирующие различные ОС и обеспечивающие реализацию безопасности.

Ядро Windows разработано в объектно-ориентированном стиле и использует два набора системных объектов – объекты-диспетчеры и управляющие объекты.

Ядро поддерживает процессы и потоки. Используется гибкая система приоритетов, включающая поддержку потоков реального времени и разделения времени. Процессы реального времени планируются как soft real-time (без обязательности выдерживания фиксированного интервала времени ответа).

Ядро обеспечивает обработку прерываний и системный механизм исключений. Для синхронизации процессов ядра используются блокировщики типа spin locks.

Менеджер системных объектов обеспечивает генерацию системных объектных ссылок (object handles) и выполнение базовых операций над объектами. Поддерживается именование объектов и объекты – символические ссылки. Каждый объект защищен списком управления доступом.

Для реализации виртуальной памяти используется двухуровневая таблица страниц с размером страницы 4 килобайта. Используются файлы откачки.

Менеджер ввода-вывода поддерживает синхронные и асинхронные операции, тайм-ауты для драйверов, кэширование ввода-вывода, использование файлов, отображаемых в память.

Монитор безопасности использует маркеры безопасности процессов и списки управления доступом к объектам для авторизации.

Менеджер PnP отслеживает изменения в конфигурации и установку соответствующих драйверов новых устройств.

Подсистемы окружения Windows: подсистема Win32; DOS Virtual Machine; подсистема Windows on Windows (исполнение 16-битовых приложений Windows); подсистема POSIX, подсистема OS/2; подсистема входа и безопасности (управляет учетными записями пользователей, используя Kerberos-аутентификацию по умолчанию).

Читайте также: