Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
СКТ - 5,6сем.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
8.67 Mб
Скачать

Синхронизация процессов и цепочек

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

Win32 API имеет четыре основных объекта для того, чтобы решить проблему синхронизации:

  • события

  • семафоры

  • взаимоисключения

  • критические секции.

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

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

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

Parbegin

цепочка 1:

{часть кода 1}

while not флаг_сортировки do ;

{ часть кода 2}

цепочка 2:

флаг_сортировки:=false;

сортировка

флаг_сортировки:=true;

parend.

Посредствам функций “создание и открытия события” (CreateEvent или OpenEvent) программа получает дескриптор, указывающий на некоторое событие. Затем вызывается функция ожидания события (WaitForSingleObject), получающая дескриптор события и указанный промежуток времени его ожидания. После этого цепочка будет заблокирована до тех пор, пока какая-либо другая цепочка в текущем или другом процессе не выдаст сигнал, что событие произошло. После сигнала о произошедшем событии заблокированная цепочка активируется и продолжает выполняться. Например, если одна цепочка использует результаты сортировки, проводимой другой цепочкой, можно воспользоваться глобальной переменной-флагом, устанавливаемый сортирующей цепочкой по завершении сортировки. При этом цепочка будет возвращаться в цикле постоянно проверяя значение флага. В результате опрашивающая цепочка впустую израсходует множество циклов процессора. Другой способ - сортирующая цепочка создает событие, которое укажет, что сортировка завершена. Цепочка, ожидающая сортировку вызовет функцию ожидания (WaitFocSingleObject), передав ей дескриптор события, созданный раньше. Это приведет к тому, что цепочка окажется заблокированной и процессор не будет задействован. Когда сортирующая цепочка завершит сортировку, она сообщит, что событие произошло и заставит исходную цепочку активизироваться и возобновить выполнение. При этом не только процессор будет использоваться эффективно, но и не возникнет проблема параллелизма, т.е. цепочка не будет использовать еще не отсортированные данные.

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

Для получения доступа к семафору цепочка вызывает функцию CreateSemaphore. При вызове этой функции необходимо указать сколько цепочек могут одновременно использовать данный ресурс или код. Если семафор будет использоваться в рамках только одного процесса, другие цепочки смогут получить дескриптор семафора с помощью глобальной переменной. Если некоторые цепочки находятся в другом процессе, чтобы получить дескриптор следует вызвать функцию OpenSemaphore. Когда цепочке потребуется доступ к совместно используемому ресурсу, она передает имя этого ресурса функции ожидания (WaitForSingleObject). Если семафор еще не затребован максимальным числом цепочка, функция ожидания увеличивает число цепочек - пользователей семафора и цепочка продолжит выполнение. Если семафор работает с максимальным числом цепочек, то цепочка, вызвавшая функцию ожидания, окажется заблокированной до тех пор, пока какая-либо другая цепочка не освободит семафор.

Третьим типом объекта синхронизации является взаимоисключение.

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

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

Алгоритм организации критических секций основан на алгоритме Деккера.

Var c1,c2: boolean;

CRITICAL_SECTION: 0..1;

parbegin

цепочка 1:

while true do

begin цеп1 желает войти в критич. секцию

c1:=EnterCriticalSection;

while c2 do пока цеп2 тоже желает в крит. секцию

if CRITICAL_SECTION=1 then проверить, если секция

begin занята (глоб. пер.), то

c1:=false; отказаться от входа и ждать

while CRITICAL_SECTION=1 do ; пока освободится

c1:= EnterCriticalSection; как свободна - сразу

end;

CRITICAL_SECTION:=1; перехват

{критическая секция}

c1:=false; освободить глоб. перем.

CRITICAL_SECTION:=0;

{остаток цепочки 1}

end;

цепочка 2:

while true do

begin …. end;

parend.

Итак, любая цепочка может находиться в одном из трех состояний:

  1. активная цепочка, т.е. цепочка фактически работает. Когда цепочка находится в работающем состоянии, все другие цепочки процесса приостанавливаются.

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

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

Понятие сообщения

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

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

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

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

Для вывода сообщения необходимо указать четыре параметра: идентификатор окна, тип сообщения, значение lParam и значение wParam. Все элементы сообщения 32-битные.

Идентификатор окна – это ссылка на объект, определенный в виде структуры данных. Если окна выглядят и ведут себя одинаково, то говорят, что они принадлежат к одному классу окон. Создаваемые пользователем окна могут обладать различными характеристиками (разные размеры, цвет, заголовок и т. д.). Объединение окон в классы позволяет уменьшить объем обрабатываемой информации (одна функция обработки, общие параметры класса). На базе одного класса окон можно создать много окон, и одна функция окна может обрабатывать сообщения для нескольких окон приложения. В таком случае приложение будет по идентификатору определять, какое окно получило сообщение.

Тип сообщения – это одна из констант, определенных в файле WinTypes.pas. Константы имеют префикс WM_, за которым следует мнемоника, указывающая назначение сообщений или источник события (WM_SIZE, WM_PAINT).

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

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

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

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

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

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

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

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

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

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

Существуют три типа асинхронных сообщений:

  • сообщения перерисовки;

  • сообщения таймера;

  • сообщение выхода.

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

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

Способ передачи сообщений, направленных одновременно в разные приложения называется приоритетом распределения.

При каждом запуске приложения Windows присваивает ему один из четырех уровней приоритета.

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