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

5.1 События

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

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

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

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

Событиями используются функции CreateEvent, OpenEvent, SetEvent, ResetEvent и PulseEvent.

HANDLE CreateEvent ( LPSECURITY_ATTRIBUTES lpsa,

BOOL fManualReset, BOOL fInitialState, LPCTSTR lpszEventName)

При установленном в значение TRUE параметре fManualReset создается событие с ручным сбросом. Аналогично, если событие первоначально должно находиться в сиг­нальном состоянии, параметр fInitialState необходимо установить в значение TRUE. Чтобы открыть существующее событие, возможно, из другого процесса, следует воспользоваться функцией OpenEvent.

Для управления событиями используются следующие три функции:

BOOL SetEvent (HANDLE hEvent)

BOOL ResetEvent (HANDLE hEvent;

BOOL PulseEvent (HANDLE hEvent)

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

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

Функция PulseEvent освобождает все события, выполняющие ожидание для дан­ного события с ручным сбросом, которое затем сбрасывается автоматически. В случае события с автосбросом функция PulseEvent освобождает единственное ожидающее событие, если таковое существует.

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

Обзор: четыре модели использования событий

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

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

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

Резюме по использованию событий

События с автосбросом

События с ручным сбросом

Функция SetEvent

Освобождается один поток. Если ни один поток в данный момент не вы­полняет ожидание для данного собы­тия, первый же поток, который начнет ожидание в дальнейшем, будет не­медленно освобожден. Событие бу­дет сброшено автоматически

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

Функция PulseEvent

Освобождается один поток, но только в случае, если поток в дан­ный момент выполняет ожидание для данного события

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

5.2 Дополнительные сблокированные функции

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

Сблокированный обмен записывает одну переменную в другую:

LONG InterlockedExchange ( LPLONG Target, LONG Value)

Функция возвращает текущее значение переменной *Target и присваивает ей значение Value. Переменная Target должна выравниваться по словам.

Функция InterlockedExchangeAdd добавляет к первому значению второе.

LONG InterlockedExchangeAdd ( PLONG Addend, LONG Increment)

Переменная Increment прибавляется к переменной *Addend, и возвращается исходное значение *Addend. Эта функция позволяет выполнить атомарную операцию увеличения переменной на 2 (или большее число), что невозможно сделать последовательными вызовами функции InterlockedIncrement.

Последняя функция, InterlockedCompareExchange, аналогична функции InterlockedExchange, за исключением того, что обмен возможен только в том слу­чае, если равенство выполняется.

PVOID InterlockedCompareExchange ( PVOID *Destination,

PVOID Exchange, PVOID Comparand)

Эта функция выполняет в атомарной операции следующие действия (причина ис­пользования типа pvoid для двух последних параметров непонятна):

Temp = *Destination;

if (*Destination == Comparand) *Destination = Exchange;

return Temp;

Одно из применений этой функции — блокировка для реализации критической секции кода. Переменная *Destination является "переменной блокировки", для ко­торой 1 значит "разблокировано", а 0 — "заблокировано". Переменная Exchange должна иметь значение 0, a Comparand — значение 1. Вызвавший функцию поток по­лучает во "владение" критическую секцию, если функция возвращает значение 1. Иначе он должен "заснуть" или "зациклиться" — выполнять бесполезный цикл неко­торое время, а затем попробовать снова. Это зацикливание — именно то, что делает функция EnterCriticalSection во время ожидания для объекта CRITICAL_SECTION с ненулевым значением счетчика цикла.

Лекция 6. Тема: Управление памятью. Использование виртуальной памяти

Архитектура управления памятью.

Каждый процесс Win32 имеет собственное виртуальное адресное пространство размером 4Гбайт (232 байт). Win32 делает доступной процессу по меньшей мере его половину (2Гбайт). Остальная часть виртуального адресного пространства предназначена для совместно используемых данных и кода, системного кода, драйверов и т.п.

Обзор управления памятью.

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

  • Система имеет сравнительно малый объем физической памяти.

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

  • Операционная система отображает виртуальные адреса в физические.

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

На рис. 6.1 показан механизм управления памятью в API Win32, основанный на диспетчере виртуальной память (Virtual Memory Manager). API виртуальной памяти Win32 (функции VirtualAlloc, VirtualFree, VirtualLock, VirtualUnlock и т.д. работает с целыми страницами. API “кучи” Win32 может работать с единицами память, определяемыми пользователем.

Функция VitualAlloc распределяет ряда страниц в виртуальном адресном пространстве, а функция VitualAllocEx распределяет ряд страниц в виртуальном адресном пространстве указанного процесса.

LPVOID VitualAlloc ( LPVOID lpvAddress, DWORD dwSize,

DWORD dwAllocationType, DWORD dwProtect).

LPVOID VitualAllocEx ( HANDLE hProcess, LPVOID lpvAddress,

DWORD dwSize, DWORD dwAllocationType, DWORD dwProtect).

Функция VirtualFree освобождает ряд страниц в виртуальном адресном пространстве. А функция VirtualFreeEx освобождает ряд страниц в виртуальном адресном пространстве указанного процесса.

BOOL VirtualFree(LPVOID lpvAddress, DWORD dwSize, DWORD dwFreeType)

BOOL VirtualFreeEx(HANDLE hProcess, LPVOID lpvAddress, DWORD dwSize,

DWORD dwFreeType)

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

BOOL VirtualLock(LPVOID lpvAddress, DWORD dwSize),

BOOL VirtualUnlock(LPVOID lpvAddress, DWORD dwSize)

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

BOOL VirtualProtect(LPVOID lpvAddress, DWORD dwSize, DWORD dwNewProtect,

DWORD pdwOldProtect)

BOOL VirtualProtectEx(HANDLE hProcess, LPVOID lpvAddress, DWORD dwSize,

DWORD dwNewProtect, DWORD pdwOldProtect)

Лекция 7. Тема: Динамически распределяемая память

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]