Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
yubuzova_umk_tehnol_sistem_2011.pdf
Скачиваний:
13
Добавлен:
13.03.2015
Размер:
660.42 Кб
Скачать

Функция берет запись в таблице описателей одного процесса и создает ее копию в таблице другого.

Завершение процесса. Процесс можно завершить четырьмя способами:

-входная функция первичного потока возвращает;

-один из потоков процесса вызывает функцию ExitProcess;

-поток другого процесса вызывает функцию TerminateProcess;

-все потоки процесса умирают по своей воле.

Функция ExitProcess. Процесс завершается, когда один из его потоков вы-

зывает ExitProcess:

VOID ExitProcess(UINT fuExitCode);

Функция TerminateProcess. Вызов функции TerminateProcess тоже завер-

шает процесс:

BOOL TerminateProcess(HANDLE hProcess,UINT fuExitCode);

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

Завершен ли процесс, идентифицируемый параметром hProcess, и, если да, определить код завершения:

BOOL GetExitCodeProcess(HANDLE hProcess,PDWORD pdwExitCode);

Основная литература: 1[200-234], 3[75-137]

Дополнительная литература: 14[167-179]

Контрольные вопросы:

1.Какие функции используются при создании и работе с процессами.

2.Какие параметры задаются при создании процесса.

3.Каков порядок закрытия процесса.

4.Какая функция используется при задании идентификатора процесса.

5.Функции для приостановки и возобновления процесса.

Лекция 3. Потоки. Планирование потоков

Любой поток состоит из двух компонентов:

-объекта ядра;

-стека потока.

Поток (thread) определяет последовательность исполнения кода в процессе. При инициализации процесса система всегда создает первичный поток.

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

Каждый поток начинает выполнение с некоторой входной функции. В первичном потоке таковой является _tmain, или _tWinMain.

Для создания вторичного потока, в нем должна быть входная функция:

18

DWORD WINAPI ThreadFunc(PVOID pvParam){ DWORD dwResult = 0;

return(dwResult); }

Создание потока. Функция CreateThread. При каждом вызове этой функции система создает объект ядра«поток». Система выделяет память под стек потока из адресного пространства процесса.

HANDLE CreateThread(PSECURITY_ATTRIBUTES psa,

DW0RD cbStackSize, PTHREAD_START_ROUTIME pfnStartAddr, PVOID pvParam, DWORD dwCreateFlags,

PDWORD pdwThreadID);

На С/С++ используют функцию _beginthreadex из библиотеки Visual С++. unsigned long _beginthreadex(void *security, unsigned stack_size, unsigned

(*start_address)(void *), void *arglist, unsigned initflag, unsigned *thrdaddr);

psa является указателем на структуру SECURITY_ATTRIBUTES. cbStackSize

определяет, какую часть адресного пространства поток сможет использовать под свой стек. При этом CreateProcess заносит в параметр cbStack Size значение, хранящееся в самом исполняемом файле. pfnStartAddr определяет адрес функции потока, с которой должен будет начать работу создаваемый поток, а pvParam идентичен pvParam функции потока, позволяет передавать функции потока какое-либо инициализирующее значение. dwCreateFlags определяет дополнительные флаги, управляющие созданием потока. Он принимает одно из двух значений: 0 или CREATE_SUSPENDED. Флаг CREATE_SUSPENDED по-

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

Завершение потока. Функция ExitThread. Поток можно завершить принудительно, вызвав:

VOID ExitThread(DWORD dwExitCode);

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

С++.

Функция TerminateThread. Вызов этой функции также завершает поток:

BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode):

В параметр dwExiCode задается значение, которое система рассматривает как код завершения потока. После того как поток будет уничтожен, счетчик пользователей его объекта ядра «поток» уменьшится на 1.

Функции ExitProcess и TerminateProcess, тоже завершают потоки.

BOOL GetExitCodeThread( HANDLE hThread, PDWORD pdwExitCode);

Код завершения возвращается в переменной типаDWORD, на которую указывает pdwExitCode.

19

Внутреннее устройство потока. В Windows предусмотрены функции,

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

HANDLE GetCurrentProcess();

HANDLE GetCurrentThread();

Поток может запросить все временные показатели своего процесса, вызвав

GetProcessTimes:

FILETIME ftCreationTime, ftExitTiroe, ftKernelTiroe, ftUserTime; GetProcessTimes(GetCurrentProcess(),

&ftCreationTime, &ftExitTiroe, &ftKernelTiroe, &ftUserTime);

Аналогичным образом поток может выяснить собственные временные показатели, вызвав GetThreadTimes:

FILETIME ftCreationTime, ftExitTime, ftKernelTiroe, ftUserTiroe; GetThreadTimes(GetCurrentThread(),

&ftCreationTime, &ftExitTime, &ftKernelTime, &ftUserTime);

Определить идентификатор - собственный или своего процесса:

DWORD GetCurrentProcessId();

DWORD GetCurrentThreadId();

Планирование потоков, приоритет и привязка к процессорам. Windows

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

Windows Vista поддерживает расширения, приближающие ее к ОС реального времени. К таким расширениями относятся службыThread Ordering и Multimedia Class Scheduler для мультимедийных приложений, таких как

Windows Media Player 11.

Приостановка и возобновление потоков. Выполнение потока можно приостановить не только при его создании с флагом CREATE_ SUSPENDED, но и вызовом SuspendThread:

DWORD SuspendThread(HANDLE hThread);

Любой поток может вызвать эту функцию и приостановить выполнение другого потока (конечно, если его описатель известен). Как и ResumeThread, функция SuspendThread возвращает предыдущее значение счетчика простоев данного потока.

Приостановка и возобновление процессов. Приостановить все потоки оп-

ределенного процесса можно из другого процесса, причем он должен быть от-

ладчиком и вызывать функции вроде WaitForDebugEvent и ContinueDebugEvent.

Того же можно добиться с помощью командыSuspend Process утилиты Process Explorer от Sysinternals она приостанавливает все потоки процесса.

Переключение потоков. Функция SwitchToThread позволяет подключить к процессору другой поток (если он есть):

BOOL SwitchToThread();

SwitchToThread позволяет потоку, которому не хватает процессорного времени, отнять этот ресурс у потока с более низким приоритетом. Вызов

20

SwitchToThread аналогичен вызову Sleep с передачей в dwMilliseconds нулевого значения.

Определение периодов выполнения потока. Windows есть функция опре-

деляющая время затраченное потоком на выполнение той или иной операции:

BOOL GetThreadTimes( HANDLE hThread, PFILETIME pftCreationTime, PFILETIME pftExitTime, PFILETIME pftKernelTime, PFILETIME pftUserTime);

Структура CONTEXT. Система сохраняет в ней состояние потока перед самым отключением его от процессора, благодаря чему его выполнение возобновляется с того места, где было прервано. Эта структура разбита на несколько разделов: CONTEXT_CONTROL, CONTEXT_INTEGER, CONTEXT_FLOATING_POINT, CONTEXT_DEBUG_REGISTERS, CONTEXT_EXTENDED_REGISTERS.

Получить сведения о текущем состоянии регистров процессора предназначена функция:

BOOL GetThreadContext(HANDLE hThread, PCONTEXT pContext);

Значения элементов CONTEXT можно изменять и передавать объекту ядра «поток» с помощью функции SetThreadContext.

BOOL SetThreadContext( HANDLE hThread, CONST CONTEXT *pContext);

Приоритеты потоков. Каждому потоку присваивается уровень приоритета - от 0 (самый низкий) до 31 (самый высокий). При загрузке системы создается особый поток - поток обнуления страниц (zero page thread), которому присваивается нулевой уровень приоритета.

Windows поддерживает шесть классов приоритета: idle (простаивающий), below normal (ниже обычного), normal (обычный), above normal (выше обычного), high (высокий) и realtime (реального времени). Самый распространенный класс приоритета - normal; его использует 99% приложений.

Относительные приоритеты потоков. Windows поддерживает семь от-

носительных приоритетов потоков: idle (простаивающий), lowest (низший), below normal (ниже обычного), normal (обычный), above normal (выше обычного), highest (высший) и time-critical (критичный по времени). Эти приоритеты относительны классу приоритета процесса. Как обычно, большинство потоков использует обычный приоритет.

Уровень приоритета формируется самой системой, исходя из класса приоритета процесса и относительного приоритета потока.

Динамическое изменение уровня приоритета потока. Две функции, по-

зволяющие отключать механизм:

BOOL SetProcessPriorityBoost(HANDLE hProcess,

BOOL bDisablePriorityBoost);BOOL SetThreadPriorityBoost( HANDLE hThread,BOOL bDisablePriorityBoost);

21

SetProcessPriorityBoost заставляет систему включить или отключить изме-

 

нение

приоритетов

всех

потоков

в

указанном,

а

про

SetThreadPriorityBoost действует применительно к отдельным потокам.

BOOL GetProcessPriorityBoost(HANDLE hProcess,

PBOOL pbDisablePriorityBoost);BOOL GetThreadPriorityBoost( HANDLE hThread,PBOOL pbDisablePriorityBoost);

Основная литература: 1[237-268], 3[197-233]

Дополнительна литература: 14[199-220]

Контрольные вопросы:

1.Понятие «поток».

2.Функция создания и завершения потока.

3.Приоритеты потока и способы изменения приоритета.

4.Управление потоками.

5.Относительные приоритеты потоков.

Лекция 4. Синхронизация потоков. Синхронизация потоков с использованием объектов ядра

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

Wait-функции позволяют потоку в любой момент приостановиться и ждать освобождения какого-либо объекта ядра. Из всего семейства этих функ-

ций чаще всего используется WaitForSingleObject:

DWORD WaitForSingleObject(HANDLE hObject, DWORD dwMilliseconds);

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

WaitForSingleObject(hProcess, INFINITE);

Функция WaitForMultipleObjects аналогична WaitForSingleObject с тем ис-

ключением, что позволяет ждать освобождения сразу нескольких объектов или какого-то одного из списка объектов:

DWORD WaitForMultipleObjects( DWORD dwCount, CONST HANDLE* phObjects, BOOL bWaitAll, DWORD dwMilliseconds);

Побочные эффекты успешного ожидания. Успешный вызов

WaitForSingleObject или WaitForMultipleObjects меняет состояние некоторых объектов ядра. Успешным вызовом будет тот, при котором функция видит, что объект освободился, и возвращает значение, относительное WAIT_OBJECT_0. Вызов считается неудачным, если возвращается WAIT_TIMEOUT или WAIT_FAILED. Изменение состояния объекта в результате вызова называется

побочным эффектом успешного ожидания (successful wait side effect).

22

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

Объекты - события бывают двух типов: со сбросом вручную (manual-reset events) и с автосбросом (autoreset events).

Объект ядра «событие» создается функцией CreateEvent:

HANDLE CreateEvent( PSECURITY_ATTRIВUTES psa, BOOL bManualReset, BOOL bInitialState, PCTSTR pszName);

bManualReset (булева переменная) сообщает системе о типе создания со-

бытия: со сбросом вручную (TRUE) или с автосбросом (FALSE).

В Windows Vista поддерживается новая функция для создания объектов-

событий, CreateEventEx.

HANDLE CreateEventEx( PSECURITY_ATTRIBUTES psa, PCTSTR pszName, DWORD dwFlags, DWORD dwDesiredAccess);

Параметр dwFlags принимает две битовые маски (таблица 4.1).

Таблица 4.1 Флаги функции

Константы,

определенные

в

Описание

 

WinBase.h

 

 

 

 

 

CREATE_EVENT_INITIAL_SET

Эквивалент

параметра bInitialState,

передаваемого

(0x00000002)

 

функции CreateEvent. Если

установлен

соответствую-

 

 

щий битовый флаг, событие инициализируется как сво-

 

 

бодное, а в противном случае - как занятое.

CREATE_EVENT_MANUAL_RESET

Эквивалент

параметра bManualReset,

передаваемого

(6x00000001)

 

функции CreateEvent. Если

установлен

соответствую-

 

 

щий битовый флаг, событие инициализируется как со-

 

 

бытие с ручным сбросом, а в противном случаекак

 

 

событие с авто-сбросом.

 

 

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

HANDLE OpenEvent( DWORD dwDesiredAccess, BOOL bInherit, PCTSTR pszName);

Ненужный объект ядра «событие» следует закрыть вызовом CloseHandle. Создав событие, можно напрямую управлять его состоянием. Чтобы перевести его в свободное состояние, вызываем:

BOOL SetEvent(HANDLE hEvent);

А чтобы поменять его на занятое:

BOOL ResetEvent(HANDLE hEvent);

Функция, которую можно использовать с объектами-событиями:

BOOL PulseEvent(HANDLE hEvent);

23

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

Ожидаемые таймеры (waitable timers) - это объекты ядра, которые самостоятельно переходят в свободное состояние в определенное время или через регулярные промежутки времени. Чтобы создать ожидаемый таймер, достаточ-

но вызвать функцию CreateWaitableTimer.

HANDLE CreateWaitableTimer( PSECURITY_ATTRIВUTES psa, BOOL bManualReset, PCTSTR pszName);

Любой процесс может получить свой(«процессозависимый») описатель существующего объекта «ожидаемый таймер», вызвав OpenWaitableTimer.

HANDLE OpenWaitableTimer( DWORD dwDesiredAccess, BOOL bInheritHandle, PCTSTR pszName);

Чтобы сообщить таймеру, в какой момент он должен перейти в свободное состояние, вызывается функция SetWaitableTimer.

BOOL SetWaitableTimer( HANDLE hTimer, const LARGE_INTEGER *pDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, PVOID pvArgToCompletionRoutine, BOOL bResume);

Ожидаемые таймеры и АРС-очередь. Существует возможность создать очередь асинхронных вызовов процедур (asynchronous procedure call, APC) для потока, вызывающего SetWaitableTimer в момент, когда таймер свободен. Когда при обращении к функции SetWaitableTimer в параметрах pfnCompletionRoutine

и pvArgToCompletionRoutine передается NULL, объект-таймер переходит в свободное состояние в заданное время. Чтобы таймер в этот момент поместил в очередь вызов АРС-функции, нужно реализовать данную функцию и передать ее адрес в SetWaitableTimer. АРС-функция должна выглядеть примерно так:

VOID APIENTRY TimerAPCRoutine(PVOID pvArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue) {

}

Семафоры. Объекты ядра «семафор» используются для учета ресурсов. Как и все объекты ядра, они содержат счетчик числа пользователей, но, кроме того, поддерживают два 32-битных значения со знаком: одно определяет максимальное число ресурсов(контролируемое семафором), другое используется как счетчик текущего числа ресурсов.

HANDLE CreateSemaphore(PSECURITY_ATTRIBUTE psa, LONG lInitialCount,LONG lMaximumCount,PCTSTR pszName);

Следующая функция позволяет напрямую предоставить права доступа, указав их в параметре dwDesiredAccess.

dwFlags зарезервирован и должен быть установлен в 0.

HANDLE CreateSemaphoreEx(PSECURnY_ATTRIBUTES psa, LONG lInitialCount,LONG lMaximumCount,PCTSTR pszName, DWORD dwFlags,DWORD dwDesiredAccess);

Любой процесс может получить свой(«процессозависимый») описатель существующего объекта «семафор», вызвав OpenSemaphore.

24

HANDLE OpenSemaphore(DWORD dwDesiredAccess, BOOL bInheritHandle,PCTSTR pszName);

Семафоры выполняют операцию проверки и присвоения на уровне -ато марного доступа.

Поток увеличивает значение счетчика текущего числа ресурсов, вызывая функцию ReleaseSemaphore:

BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount,PLONG plPreviousCount);

Мьютексы. Объекты ядра «мьютексы» гарантируют потокам взаимоисключающий доступ к единственному ресурсу. Они содержат счетчик числа пользователей, счетчик рекурсии и переменную, в которой запоминается идентификатор потока. Для использования объекта-мьютекса один из процессов должен сначала создать его вызовом CreateMutex.

HANDLE CreateMutex(PSECURITY_ATTRIBUTES psa, BOOL bInitialOwner,

PCTSTR pszName);

Следующая функция позволяет напрямую передать права доступа, указав их в параметре dwDesiredAccess.

HANDLE CreateMutexEx( PSECURITY_ATTRIBUTES psa, PCTSTR pszName,

DWORD dwFlags, DWORD dwDesiredAccess);

Любой процесс может получить свой(«процессозависимый») описатель существующего объекта «мьютекс», вызвав OpenMutex.

HANDLE OpenMutex( DWORD dwDesiredAccess, BOOL bInheritHandle, PCTSTR pszName);

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

BOOL ReleaseMutex(HANDLE hMutex);

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

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

Таблица 4.2 Объекты ядра и синхронизация потоков

Объект

Находится в занятом

-со Переходит в свободное

-

соПобочный

 

стоянии, когда:

стояние, когда:

 

эффект успеш

 

 

 

 

ного ожидания

1

2

3

 

4

Процесс

процесс еще активен

процесс завершается

 

Нет

25

 

 

 

 

 

 

 

 

 

 

(ExitProcess,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

TerminateProcess)

 

 

 

 

 

 

 

Поток

 

 

поток еще активен

 

 

 

поток

 

 

 

завершаетсяНет

 

 

 

 

 

 

 

 

 

 

 

 

 

 

(ExitThread,TerminateThread)

 

 

 

 

 

 

Задание

 

 

время,

выделенное

 

зада-

время,

выделенное

заданию,

 

Нет

 

 

 

 

 

 

 

нию, еще не истекло

 

 

истекло

 

 

 

 

 

 

 

 

Файл

 

 

выдан

запрос

на

-

вводзавершено выполнение запро-

 

Нет

 

 

 

 

 

 

 

вывод

 

 

 

 

 

 

са на ввод-вывод

 

 

 

 

 

 

 

Консольный ввод

ввода нет

 

 

 

 

 

ввод есть

 

 

 

Нет

 

 

 

 

Уведомление об

в файловой

системе

 

нетфайловая

система обнаружи-

 

Сбрасывается

 

в

 

 

изменении файла

изменений

 

 

 

 

 

вает изменения

 

 

исходное

-

 

со

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

стояние

 

 

 

 

Событие с авто-

вызывается

 

ResetEvent,

вызывается

SetEvent или

 

Сбрасывается

 

 

 

 

сбросом

 

 

PulseEvent

или

ожидание

PulseEvent

 

 

 

в исходное

 

 

 

 

 

 

 

успешно завершилось

 

 

 

 

 

 

 

состояние

 

 

 

 

Событие

 

со сбро-

вызывается ResetEvent или

вызывается SetEvent или Pul-

 

Нет

 

 

 

 

сом вручную

PulseEvent

 

 

 

 

 

seEvent

 

 

 

 

 

 

 

 

 

Ожидаемый

вызывается

 

 

 

 

 

наступает

время

срабатыва-

 

Сбрасывается

 

в

 

 

таймер

с

автосбро-

CancelWaitable

 

 

 

 

ния (SetWaitableTimer)

 

исходное

-

 

со

сом

 

 

Timer или

ожидание

ус-

 

 

 

 

 

стояние

 

 

 

 

 

 

 

пешно завершилось

 

 

 

 

 

 

 

 

 

 

 

 

 

Ожидаемый

вызывается

 

 

 

 

 

наступает

время

срабатыва-

 

Нет

 

 

 

 

таймер со сбро-

CancelWaitableTimer

 

 

ния (SetWaitableTimer)

 

 

 

 

 

 

сом вручную

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Семафор

 

 

ожидание

успешно

завер-

счетчик>0 (ReleaseSemaphore)

 

Счетчик

 

 

 

 

 

 

 

шилось

 

 

 

 

 

 

 

 

 

 

 

уменьша

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ется на 1

 

 

 

 

Мьютекс

 

 

ожидание

успешно

завер-

поток

освобождает

мьютексПередается

 

 

 

 

 

 

 

шилось

 

 

 

 

 

 

{ReleaseMutex)

 

 

потоку во

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

владение

 

 

 

 

Критическая

ожидание

успешно

завер-

поток

освобождает

критиче-

Передается

 

 

 

 

секция (пользо-

шилось

 

 

 

 

 

 

скую

 

 

 

 

потоку секциюво

 

 

 

 

вательского ре-

((Try)EnterCriticalSection)

 

(LeaveCriticalSection)

 

 

владение

 

 

 

 

жима)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

SRWLock

(пользо-

ожидание

успешно

завер-

поток

освобождает SRWLock

Передается

 

 

 

 

вательского

режи-

шилось

(AcquireSRWLock

(ReleaseSRWLock (Exclusive))

потоку во

 

 

 

 

ма)

 

 

(Exclusive))

 

 

 

 

 

 

 

 

 

 

владение

 

 

 

 

Условная пере

ожидание

успешно

завер-

поток пробуждается

 

 

Нет

 

 

 

 

менная

(пользова-

шилось

 

 

 

 

 

 

(Wake(All)ConditionVariable)

 

 

 

 

 

тельского режима)

(SleepConditionVariable)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Основная литература: 1[271-307], 3[280-327]

Дополнительная литература: 14[228-258]

Контрольные вопросы:

1.Функция Windows Vista для создания объектов-событий.

2.Объекты ядра и синхронизация потоков.

3.Ожидаемые таймеры, принцип действия.

4.Назначение объектов «семафор», «мьютексы», принцип функциониро-

вания.

5.Какая функция применяется для передачи прав доступа.

26

Лекция 5. Синхронизация потоков. Синхронизация потоков в пользовательском режиме

Потоки должны взаимодействовать друг с другом в двух основных случа-

ях:

-совместно используя разделяемый ресурс (чтобы не разрушить его);

-когда нужно уведомлять другие потоки о завершении каких-либо опера-

ций.

 

 

 

 

Атомарный доступ: семейство Intelocked-функций. Большая часть син-

 

хронизации потоков связана сатомарным доступом (atomic access) - моно-

 

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

 

 

Все функции из семействаInterlocked-функций манипулируют перемен-

 

ными на уровне атомарного доступа. InterlockedExchangeAdd и ее 64-разрядная

 

версия

InterlockedExchangeAdd64,

манипулируют

значениями

типа

LONGLONG:

LONG InterlockedExchangeAdd( PLONG volatile plAddend, LONG lIncrement);

LONGLONG InterlockedExchangeAdd64( PLONGLONG volatile pllAddend, LONGLONG llIncrement);

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

Библиотека С поддерживает функцию _aligned_malloc, которая служит для выделения надлежащим образом выровненных блоков памяти. Прототип функции:

void * _aligned_malloc(size_t size, size_t alignment);

Функции из этого семейства:

LONG InterlockedExchange( PLONG volatile plTarget, LONG lValue); LONGLONG InterlockedExchange64( PLONGLONG volatile plTarget, LONGLONG lValue); PVOID InterlockedExchangePointer( PVOID* volatile ppvTarget, PVOID pvValue);

Interlocked-функции выглядят так:

PVOID InterlockedCompareExchange( PLONG plDestination, LONG lExchange, LONG lComparand);

PVOID InterlockedCompareExchangePointer( PVOID* ppvDestination, PVOID pvExchange, PVOID pvComparand);

B Windows XP и последующих версиях к вышеописанным атомарным операциям над целочисленными и булевыми значениями добавлен ряд функций, позволяющих без особого труда манипулировать стеком, известным также как InterlockedSinglyLinkedList (однонаправленный список с взаимоблокировкой). Все операции над таким стеком, такие как заталкивание в него значений и извлечение значений выполняются атомарно.

27

Критическая секция (critical section) - это небольшой участок кода, требующий монопольного доступа к каким-то общим данным. Позволяет устанавливать доступ к определенному ресурсу единовременно только одному потоку.

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

Если есть ресурс, разделяемый несколькими потоками, необходимо создать экземпляр структуры CRITICAL_SECTION. Любой участок кода, работаю-

щий с разделяемым ресурсом, нужно заключить в вызовы функций

EnterCriticalSection и LeaveCriticalSection.

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

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

Структуры CRITICAL_SECTION создаются как глобальные переменные, доступные всем потокам процесса. Структура инициализируется вызовом:

VOID InitializeCriticalSection(PCRITICAL_SECTION pcs);

Эта функция инициализирует элементы структуры CRITICAL_SECTION, на которую указывает параметр pcs. Если структура CRITICAL_SECTION больше не понадобится ни одному ,потокунеобходимо удалить , еевызвав

DeleteCriticalSection:

VOID DeleteCriticalSection(PCRITICAL_SECTION pcs);

Она сбрасывает все переменные-члены внутри этой структуры. Участок кода, работающий с разделяемым ресурсом, предваряется вызовом:

VOID EnterCriticalSection(PCRITICAL_SECTION pcs);

EnterCriticalSection передает потоку ресурс, автоматически обновляя эле-

менты структуры CRITICAL_SECTION.

Длительность времени ожидания функциейEnterCriticalSection определя-

ется значением параметра CriticalSectionTimeout.

Вместо EnterCriticalSection можно воспользоваться:

BOOL TryEnterCriticalSection(PCRITICAL_SECTION pcs);

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

VOID LeaveCriticalSection(PCRITICAL_SECTION pcs);

Функция просматривает элементы структурыCRITICAL_SECTION и уменьшает счетчик числа захватов ресурса вызывающим потоком на 1.

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

28

Для использования спин-блокировки в критической секции нужно инициализировать счетчик циклов, вызвав:

BOOL InitializeCriticalSectionAndSpinCount( PCRITICAL_SECTION pcs, DWORD dwSpinCount);

Изменить счетчик циклов спин-блокировки вызовом:

DWORD SetCriticalSectionSpinCount( PCRITICAL_SECTION pcs, DWORD dwSpinCount);

«Тонкая» блокировка. У «тонкой» блокировки чтения и записи(slim reader-writer lock), называемой также SRWLock, назначение: защита ресурса от одновременного доступа разных потоков. Сначала следует объявить структуру SRWLOCK и инициализировать ее вызовом InitializeSRWLock:

VOID InitializeSRWLock(PSRWLOCK SRWLock);

После инициализации SRWLock записывающий поток может попытаться получить монопольный доступ к ресурсу, защищенному SRWLock, вызвав функцию AcquireSRWLockExclusive и передав ей в качестве параметра адрес объекта SRWLOCK:

VOID AcquireSRWLockExclusive(PSRWLOCK SRWLock);

После модификации ресурса блокировку освобождают вызов ReleaseSRWLockExclusive с передачей в качестве параметра адреса объекта

SRWLOCK:

VOID ReleaseSRWLockExclusive(PSRWLOCK SRWLock);

В случае читающего потока все аналогично, только используются другие функции:

VOID AcquireSRWLockShared(PSRWLOCK SRWLock);

VOID ReleaseSRWLockShared(PSRWLOCK SRWLock);

Результаты теста затраченного времени на двухпроцессорном компьютере показаны в таблице 5.1.

Таблица 5.1 Сравнение производительности различных механизмов синхронизации

Число

 

 

 

Время (мс)

 

 

 

пото-

Чтение без

Запись без

Приращение

 

SRWLock кри-

SRWLoc

(об-

Мью-

ков

синхрони-

синхрони-

(Interlocked)

 

тическая сек-

k (об-

щий

текс

 

зации

зации

 

 

ция

щий

дос-

 

 

 

 

 

 

 

доступ)

туп)

 

1

8

8

8

 

35

66

66

1060

2

8

76

153

 

268

134

148

11082

4

9

145

361

 

768

244

307

23785

В ячейках таблицы 4.1 показано время, прошедшее от запуска потоков до завершения исполнения последним потоком 1000000 следующих операций:

- чтение (без синхронизации) значения типа long:

LONG lValue = gv_value;

29

- запись (без синхронизации) значения типа long: gv_value = 0;

- безопасное приращение long-значения с помощью функции

InterlockedIncre-ment. InterlockedIncrement(&gv_value);

- чтение long-значения с использованием критической секции:

EnterСriticalSection(&g_cs); gv_value = 0; LeaveCriticalSection(&g_cs);

- чтение long-значения с помощью SRWLock:

AcquireSRWLockShared/Exclusive(&g_srwLock); gv_value = 0; ReleaseSRWLockShared/Exclusive(&g_srwLock);

- использование синхронизирующего объекта ядра«мьютекс» для чтения long-значения:

WaitForSingleObject(g_hMutex, INFINITE); gv_value = 0; ReleaseMutex(g_hMutex);

Функция WaitForInputIdle. Поток может приостановить себя и вызовом

WaitForInputIdle:

DWORD WaitForInputIdle(HANDLE hProcess, DWORD dwMilliseconds);

Функция MsgWaitForMultipleObjects(Ex). При вызове MsgWaitForMultipleObjects или MsgWaitForMultipleObjectsEx поток переходит в ожидание своих

(предназначенных этому потоку) сообщений:

DWORD MsgWaitForMultipleObjects(DWORD dwCount, PHANDLE phObjects,BOOL bWaitAll,DWORD dwMilliseconds, DWORD dwWakeMask);

DWORD MsgWaitForMultipleObjectsEx(DWORD dwCount, PHANDLE phObjects,DWORD dwMilliseconds,DWORD dwWakeMask, DWORD dwFlags);

Таблица 5.2

Типы синхронизирующих механизмов, отслеживаемых WCT

Потенциальные источники

Описание

 

блокировок

 

 

Критическая секция

Windows отслеживает критические секции и потоки, которые

 

 

ими владеют

 

Мьютексы

Windows отслеживает мьютексы (включая те, от которых отка-

 

 

зались владевшие им потоки) и потоки, которым они принадле-

 

 

жат

 

Процессы и потоки

Windows отслеживает потоки, ждущие завершения других пото-

 

 

ков и процессов

 

Вызовы SendMessage

Система отслеживает потоки, ожидающие завершения вызова

 

 

SendMessage

 

Вызовы и инициализация объ-

Вызовы CoCreateInstance и методов объектов СОМ также -от

 

ектов СОМ

слеживаются

 

Advanced Local Procedure Call

Механизма ALPC — новый незадокументированный механизм

 

(ALPC)

межпроцессной коммуникации, заменивший LPC в Windows

 

 

Vista

 

30

Основная литература: 1[271-308], 3[238-277]

Дополнительная литература: 14[228-258]

Контрольные вопросы:

1.Атомарный доступ: семейство Intelocked-функций.

2.Типы синхронизирующих механизмов.

3.Каким образом можно установить доступ к определенным ресурсам одновременно.

4.Для каких целей применяется счетчик циклов в критической секции.

5.В чем отличие тонкой блокировки.

Лекция 6. Файловая система. Управление файлами.

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

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

HANDLE CreateFile( PCTSTR pszName, DWORD dwDesiredAccess, DWORD dwShareMode, PSECURITY_ATTRIBUTES psa, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hFileTemplate);

pszName определяет тип и экземпляр устройства.

dwDesiredAccess указывает на режим доступа к файлучтение или записи, задаваемые флагами GENERIC_READ и GENERIC_WRITE. Флаги можно объединять операцией OR. Некоторые устройства поддерживают дополнительные флаги, управляющие доступом.

dwShareMode определяет совместный доступ к файлу, может объединять значения с помощью операции OR:

0 - Запрашивается монопольный доступ к устройству.

FILE_SHARE_READ - другим процессам, в том числе, который вызвал функцию, разрешается параллельное чтение файла

FILE_SHARE_WRITE - разрешается запись в файл

FILE_SHARE_ DELETE - разрешает логическое удаление или перемещение файла, даже если он еще не закрыт.

psa ссылается на структуру SECURITY_ATTRIBUTES.

dwCreationDisposition особо важен при вызовеCreateFile для открытия именно файлов, определяющий создать ли новый файл, или заменить файл, либо урезать файл.

dwFlagsAndAttributes устанавливает флаги и атрибуты. Всего 19 флагов и атрибутов.

FILE_ATTRIBUTE_ NORMAL используется в случае когда другие атрибуты не установлены.

FILE_ATTRIBUTE_ READONLY приложениям разрешено только чтение файла.

FILE_ATTRIBUTE_ TEMPORARY временный файл.

31

FILE_FLAG_DELETE_ON_CLOSE полезен для временных файлов, система удаляет файл после того, как будет закрыт последний его описатель.

FILE_FLAG_NO_BUFFERING - запрещение использования буферизации при обращении к файлу.

FILE_FLAG_SEQUENTIAL_SCAN доступ к файлу последовательный. FILE_FLAG_RANDOM_ACCESS - доступ к файлу произвольный. FILE_FLAG_WR1TE_THROUGH режим сквозной записи промежуточных

данных в файл на диске, минуя кэш.

FILE_FLAG_OVERLAPPED используется для работы с асинхронным вводом/выводом.

hFileTemplate, дескриптор файла с правами доступаGENERIC_READ, предоставляющий расширенные атрибуты для вновь создаваемого файла, при этом игнорируются значения dwFlagsAndAttributes. Если функция CreateFile открывает существующий файл параметр hFileTemplate игнорируется.

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

CloseHandle:

BOOL CloseHandle(HANDLE hobject);

Чтение файлов.

BOOL ReadFile(HANDLE hFile,PVOID pvBuffer, DWORD nNumBytesToRead,PDWORD pdwNumBytes, OVERLAPPED* pOverlapped);

hFile задает дескриптор файла, с доступом GENERIC_READ.

pvBuffer указатель на буфер для хранения прочитанных данных либо данных, подлежащих записи.

nNumBytesToRead указывает число байтов, которое следует прочитать с из файла.

pdwNumBytes указывает адрес DWORD-переменной, в которую функция записывает фактическое число байтов, прочитанное функцией.

pOverlapped в случае синхронного ввода-вывода устанавливают в NULL.

Запись в файл.

BOOL WriteFile(HANDLE hFile,CONST VOID *pvBuffer, DWORD nNumBytesToWrite,PDWORD pdwNumBytes, OVERLAPPED* pOverlapped);

nNumBytesToWrite указывает число байтов, которое следует записать на него.

WriteFile вызывают только для устройств, открытых с флагом

GENERIC_WRITE.

Удаление файла. Для этой цели используется вызов:

BOOL DeletFile( PCTSTR pszFileName);

Копирование файла.

BOOL FileCopy(PCTSTR pszFileSrc, PCTSTR pszFileDst) {

32

Определение размера файла. При работе с файлами довольно часто приходится определять их размеры. Проще всего сделать это вызовомGetFileSizeEx.

BOOL GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER pliFileSize);

hFile - идентификатор открытого файла, a pliFileSize — адрес объединенной структуры LARGEINTEGER.

typedef union _LARGE_INTEGER {

struct {DWORD LowPart; LONG HighPart; };LONGLONG QuadPart;

} LARGE_INTEGER, *PLARGE_INTEGER;

Существует функция для определения размерафа

GetCompressedFileSize:

DWORD GetCompressedFileSize(PCTSTR pszFileName, PDWORD pdwFileSizeHigh);

Эта функция возвращает физический размер файла, а GetFileSizeEx - логический размер.

Вотличие GetFileSizeEx,от первый параметр функции GetCompressedFileSize - это имя файла в виде строки, а не описателя. GetCompressedFileSize возвращает 64-разрядное значение, представляющее размер файла.

Сброс данных на устройство. Для записи кэшированных данных на устройство, используется функция FlushFileBuffers:

BOOL FlushFileBuffers(HANDLE hFile);

Эта функция принуждает систему сбросить все содержимое буферов на устройство, заданное параметром hFile. Для этого устройство должно быть открыто с флагом GENERIC_WRITE. При успешном завершении вызова функция возвращает TRUE.

Определение и изменение атрибутов файла. Узнать атрибуты файла можно с помощью функции GetFileAttributes, которая имеет следующий прототип:

DWORD GetFileAttributes( PCTSTR lpFileName );

Вслучае успешного завершения эта функция возвращает атрибуты файла,

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

-FILE_ATTRIBUTE_ARCHIVE - архивный файл;

-FILE_ATTRIBUTE_COMPRESSED - сжатый файл;

-FILE_ATTRIBUTE_DIRECTORY - файл является каталогом;

-FILE_ATTRIBUTE_ENCRYPTED - шифрованный файл;

-FILE_ATTRIBUTE_HIDDEN - скрытый файл;

-FILE_ATTRIBUTE_NORMAL - нормальный файл;

33

-FILE_ATTRIBUTE_NOT_CONTENT_INDEXED - файл не индексируется;

-FILE_ATTRIBUTE_OFFLINE - файл во внешней памяти;

-FILE_ATTRIBUTE_READONLY - файл только для чтения;

-FILE_ATTRIBUTE_REPARSE_POINT - файл требует интерпретации;

-FILE_ATTRIBUTE_SPARSE_FILE - разреженный файл;

-FILE_ATTRIBUTE_SYSTEM - системный файл;

-FILE_ATTRIBUTE_TEMPORARY - временный файл

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

Для изменения атрибутов файла используется функция SetFileAttributes:

BOOL SetFileAttributes( PCTSTR lpFileName, DWORD dwFileAttributes );

В случае успешного завершения эта функция возвращает ненулевое значение, а в случае неудачи - false.

При этом отметим, что если устанавливается флаг file_attribute_normal, тo он должен быть один, т. к. все остальные атрибуты, аннулируют этот атрибут.

Установка указателя в файле. Например, код, считывающий из файла в буфер первые 10 байтов, а затем еще 10 байтов.

BYTE pb[10];DWORD dwNumBytes;

HANDLE hFile = CreateFile(TEXT("MyFile.dat"), …); ReadFile(hFile, pb, 10, &dwNumBytes, NULL); ReadFile(hFile, pb, 10, idwNumBytes, NULL);

У каждого объекта ядра имеется свой собственный указатель. Для случайного доступа к файлу необходимо модифицировать указатель«файла» с помо-

щью функции SetFilePointerEx:

BOOL SetFilePointerEx(HANDLE hFile,

 

 

LARGE_INTEGER liDistanceToMove,

 

 

PLARGE_INTEGER pliNewFilePointer,

 

 

DWORD dwMoveMethod);

 

 

hFile определяет

указатель «файла»,

который

требуется изменить.

liDistanceToMove - на

сколько байт

следует

переместить указатель.

dwMoveMethod, указывает, как функция SetFilePointerEx должна интерпретиро-

 

вать параметр liDistanceToMove.

 

 

 

 

FILE_BEGIN - указатель перемещается в положение, заданное параметром

 

HDistanceTbMove. FILE_CURRENT - значение HDistanceTbMove прибавляется к

 

текущему значению указателя«файл». FILE_END - новая позиция указателя

 

вычисляется

как

сумма

логического

размера

файла

и

HDistanceToMove.

 

 

 

 

 

 

LARGE_IHTEGER liCurrentPosition = { 0 };

 

 

 

SetFilePointerEx(hFile,

liCurrentPosition,

&liCurrentPosition,

 

FILE_CURRENT);

 

 

 

 

 

34

Установка конца файла. Обычно система автоматически устанавливает конец файла при его закрытии. В некоторых случаях требуется принудительно сделать файл больше или меньше. Для этого вызывают следующую функцию:

BOOL SetEndOfFile(HANDLE hFile);

Функция SetEndOfFile уменьшает или увеличивает файл до размера, заданного текущим положением указателя в файле. Например, принудительно назначить файлу размер 1024 байта, с помощью SetEndOfFile следующим образом:

HANDLE hFile = CreateFile(…); LARGE_INTEGER liDistanceToMove; liDistanceToMove.QuadPart = 1024;

SetFilePointerEx(hFile, liDistanceToMove, NULL, FILE_BEGIN); SetEndOfFile(hFile);

CloseHandle(hFile);

Блокирование файла. Для организации монопольного доступа к файлу используется его блокировка или часть его, с помощью функции LockFile:

BOOL LockFile( HANDLE hFile,

DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,

DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesTiLockHigh );

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

BOOL UnlockFile( HANDLE hFile,

DWORD dwFileOffsetLow, DWORD dwFileOffsetHigh,

DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesTiLockHigh );

Основная литература: 1[51-123], 3[348-353]

Дополнительная литература: 14[34-74]

Контрольные вопросы:

1.Какие функции применяются для управления файлами.

2.Какие флаги и какие атрибуты задаются при создании и открытии фай-

лов.

3.Какая функция позволяет определять или изменять атрибут файла.

4.Как установить указатель в файл, назначение.

5.Назначение процесса блокировки и разблокировки файла.

Лекция 7. Файловая система. Управление каталогами. Реестр.

Управление каталогом. Каталогом называется файл, который содержит имена и местонахождение других файлов. Файловая система обеспечивает следующие функции для работы с каталогами:

-создание каталога;

-удаление каталога;

-включение подкаталога в каталог;

35

-исключение подкаталога из каталога;

-включение файла в каталог;

-исключение файла из каталога.

Создание каталога. Для создания каталога используется функция CreateDirectory, которая имеет следующий прототип:

BOOL CreateDirectory(

PCTSTR pszPathName, PSECUTITY_ATTRIBUTES lpSecurutyAttributes);

Поиск файлов в каталоге. Для поиска файлов, находящихся в каталоге,

используются функции FindFirstFile и FindNextFile.

FindFirstFile предназначена для нахождения первого файла в каталоге:

HANDLE FindFirstFile( PCTSTR pszFileName, PWIN32_FIND_DATA lpFindFileData );

В случае успешного завершения функцияFindFirstFile возвращает дескриптор для поиска файлов, который используется в дальнейшем функцией

FindNextFile, а в случае неудачи - значение invalid_handle_value. pszFileName - образец имени файла для поиска.

lpFindFileData указывает структуру типаwin3 2_find_data, в которую функция запишет о найденном файле. Эта структура имеет следующий формат:

typedef struct _WIN32_FIND_DATA {

DWORD dwFileAttributes; FILETIME ftCreationTime; FILETIME ftLastAccessTime; FILETIME ftLastWriteTime; DWORD nFileSizeHigh; DWORD nFileSizeLow; DWORD dwReserved0; DWORD dwReserved1; CHAR cFileName[ MAX_PATH ];

CHAR cAlternateFileName[ 14 ] ;

} WIN32_FIND_DATA/ *PWIN32_FIND_DATA, *LPWIN32_FIND_DATA;

Для нахождения следующих, после найденного первого файла, используется функция:

BOOL FindNextFilе( HANDLE hFindFile, LPWIN32_FIND_DATA lpFindFileData );

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

BOOL FindClose( HANDLE hFindFile );

hFindFile - дескриптор поиска файла. В случае успешного завершения эта функция возвращает ненулевое значение, а в случае неудачи - FALSE.

Удаление каталога. Удалить каталог можно с помощью функции RemoveDdirectory, которая имеет следующий прототип:

BOOL RemoveDirectory ( PCTSTR pszPathName );

Перемещение каталога. Каталоги можно перемещать при помощи функ-

ции MoveFile:

BOOL MoveFile( PCTSTR pszExistingFileName, PCTSTR pszNewFileName);

36

Текущие диск и каталог для процесса. Windows позволяет открывать ка-

талоги,

если

при

вызовеCreateFile

установлен

флаг

FILE_FLAG_BACKUP_SEMANTICS. Открыв каталог, можно изменять его атри-

буты.

 

 

 

 

 

Получить и установить текущий каталог и диск для процесса можно с по-

мощью функций:

 

 

 

 

DWORD GetCurrentDirectory(DWORD cchCurDir,

 

PTSTR pszCurDir);

 

 

 

 

BOOL SetCurrentDirectory(PCTSTR pszCurDir);

 

Set-

Для

смены

текущего

каталога

Windowsвместо -функции

CurrentDirectory можно использовать функцию _chdir из библиотеки С. Внутренне она тоже обращается к SetCurrentDirectory, но, кроме того, спо-

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

Родительский процесс может узнать, какие каталоги являются текущими,

вызвав GetFullPathName:

DWORD GetFullPathName(PCTSTR pszFile,

DWORD cchPath,PTSTR pszPath,PTSTR *ppszFilePart);

Например, чтобы получить текущий каталог на диске С, функцию вызвать:

TCHAR szCurDir[MAX_PATH];

DWORD cchLength = GetFullPathName(TEXT(“C:"), MAX_PATH, szCurDir, NULL);

Основные понятия о реестре Windows Vista.

-группировка данных в реестре

-типы данных, используемые в реестре

-общие правила работы с реестром

-использование REG-файлов

-резервное копирование и восстановление реестра

В операционной системеWindows специальная база данных называется системным реестром. Доступ к реестру осуществляется через разделы или ключи реестра (registry keys), выполняют ту же роль что и каталоги в файловой системе. Раздел может содержать подразделы или пары «имя-значение», в которых существует такая же взаимосвязь что и между именами файлов и их содержимым. В парах «имя-значение» реестра содержится информация:

-номер версии ОС, номер сборки и информация о зарегистрированном пользователе;

-подобная информация обо всех корректно установленных приложениях;

-информация о типе процессоров в компьютере, их количество, системной памяти и т.д.;

-информация о пользователе, включая данные основного каталога и настройки приложений;

-информация по безопасности, в том числе учетные записи пользователей;

-установленные службы;

37

-соответствие между расширениями имен файлов и исполняемыми программами, используемое системой для организации интерфейса пользователя;

-соответствие сетевых адресов с именами компьютеров.

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

-HKEY_CLASSES_ROOT.

-HKEY_CURRENT_USER

-HKEY_LOCAL_MACHINE

-HKEY_USERS

-HKEY_CURRENT_CONFIG

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

Типы данных, используемые в реестре

-REG_BINARY

-REG_DWORD

-REG_EXPAND_SZ.

-REG_MULTI_SZ

-REG_SZ

-REG_FULL_RESOURCE_DESCRIPTOR.

-REG_LINK

Кроме этого в системном реестре могут использоваться типыREG_NONE, REG_RESOURCE_LIST и др.

Управление системным реестром. Функции управления реестром позволяют запрашивать и изменять данные, относящиеся к парам «имя-значение», создавать новые подразделы и новые пары«имя-значение». Используются дескрипторы типа HKEY.

Для открытия подраздела предназначена функция RegOpenKeyEx.

LONG RegOpenKeyEx (HKEY hKey, PCTSTR lpSubKey,DWORD ulOptions, REGSAM samDesired,PHKEY phkResult)

hKey - указатель на открываемый раздел реестра или значение дескриптора одного из стандартных зарезервированных разделов.

phkResult - указатель на переменную типа HKEY, принимающую значение дескриптора открываемого раздела.

ulOptions – значение должно быть равно NULL. lpSubKey – указатель строки с именем подраздела.

samDesired – маска доступа, задающая уровень защиты нового раздела.

Значения могут бытьKEY_ALL_ACCESS, KEY_WRITE, KEY_QUERY_VALUE, KEY_ENUMARATE_SUBKEYS. В случае успешного завершения функции возвращается значение ERROR_SUCCESS. Для закрытия дескриптора открытого раздела применяется функция RegCloseKey, принимающая в качестве параметра

38

дескриптор. Для получения имен подразделов любого раздела используется функция RegEnumKeyEx. Кроме того используются функции для получения пар «имя-значение» RegEnumValue и RegQueryValueEx. RegSetValueEx сохраня-

ет данные различного типа в поле значения открытого раздела реестра. Функция RegEnumKeyEx выдает подразделы открытого раздела системного реестра также как функции FindFirstFile и FindNextFile выдают содержимое каталогов. Функция извлекает имя подраздела, строку с именем класса подраздела, а также дату и время последнего изменения.

LONG RegEnumValue (HKEY hKey, DWORD dwIndex, PTSTR lpValueName, PDWORD lpReserved, PDWORD lpType, PBYTE lpData, PDWORD lpcbData)

dwIndex устанавливается в 0 при первом вызове функции и увеличивается на 1 при каждом последующем вызове. Название раздела и его размер, строка с именем класса и ее размер, возвращаются обычным способом. При успешном завершении функция возвращает значениеERROR_SUCCESS, иначе - код ошибки.

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

LONG RegCreateKeyEx (

HKEY hKey, PCTSTR lpSubKey, DWORD Reserved, PTSTR lpClass, DWORD dwOptions, REGSAM samDesired PSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult,PDWORD lpdwDisposition)

lpSubKey имя нового подраздела, создаваемого в разделе на который указывает дескриптор hKey.

lpClass класс или тип объекта раздела, описывающий представляемые им данные. Возможные значения REG_SZ (строка, завершающаяся нулевым символом) REG_DWORD (двойное слово).

dwOptions может иметь значение 0 или одно из двух взаимоисключающих значений - REG_OPTION_VOLATILE или REG_OPTION_NON_VOLATILE. По-

стоянно хранимая (nonvolatile) информация системного реестра сохраняется в файле и после перезапуска системы восстанавливается. Непостоянные разделы хранятся в памяти и после перезапуска не восстанавливаются.

lpSecurityAttributes принимает значение 0 либо атрибуты безопасности, права доступа к разделу могут выбираться из набора значений что и samDeв - sired.

lpdwDisposition указывает на переменнуюDWORD значение которой информирует: существовал раздел ранее (REG_OPENED_EXISTING_KEY) или создается впервые (REG_CREATED_NEW_KEY).

Для удаления раздела применяется функцияRegDeleteKey. Параметрами являются - дескриптор открытого раздела и имя подраздела.

Управление параметрами. Для вывода значений параметров открытого раздела используется функция RegEnumValue. dwIndex должно быть 0 при первом вызове функции и увеличиваться на1 при каждом следующем вызове. По-

39

сле возврата из функции получим строку с именем параметра, его значением и типом, а также размером.

LONG RegEnumValue (HKEY hKey, DWORD dwIndex,

PTSTR lpValueName, PDWORD lpcbValueName, PDWORD lpReserved, PDWORD lpType, PBYTE lpData, PDWORD lpcbData)

Фактическое значение параметра возвращается в буфере, на который указывает lpcbData. Тип данных, на который указывается lpType может быть раз-

личным включая REG_BINARY, REG_DWORD, REG_SZ (строка) и

REG_EXPAND_SZ (расширяемая строка с параметрами, заменяемыми переменными окружения).

Если возвращаемое значение функции равно значениеERROR_SUCCESS, то все параметры выведены правильно.

Функция аналогична, за исключением – требует указания имени перечисленного параметра, а не его индекса. Данную функцию следует использовать в случае, когда известны имена параметров.

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

LONG R RegSetValueEx (

HKEY hKey, PCTSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE* lpData, CONST cbData)

Для удаления значений параметров используется функция RegDeleteValue.

Основная литература: 1[87-123] Дополнительная литература: 14[62-89]

Контрольные вопросы

1.Какие функции участвуют в управлении каталогами.

2.Функции поиска файлов в каталоге.

3.Какие функции используются для установки и получения текущего ка-

талога.

4.Реестр Windows Vista, разделы, назначение.

5.Какие функции применяются для группировки данных в реестре.

6.Какие функции применяются для управления системным реестром.

Лекция 8. Архитектура памяти. Управление памятью. Виртуальная память.

Каждому процессу выделяется собственное виртуальное адресное -про странство. Для 32-разрядных процессов его размер составляет4 Гб. Соответственно 32битный указатель может быть любым числом 0x00000000от до 0xFFFFFFFF. Всего, таким образом, указатель может принимать4294967296 значений, что как раз и перекрывает четырехгигабайтовый диапазон. Для 64разрядных процессов размер адресного пространства равен16 экзабайтам, поскольку 64-битный указатель может быть любым числом 0x00000000от

40

00000000 до 0xFFFFFFFF FFFFFFFF и принимать 18446744073709551616 зна-

чений, охватывая диапазон в 16 экзабайтов.

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

Основные сведения:

-система располагает небольшим объемом физической памяти;

-каждый процесс имеет собственное адресное пространство, объем которого может превышать объем доступного физического адресного пространства;

-система отображает виртуальные адреса в физические;

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

На рисунке 6.1 отражено расположение уровней API управления памятью Windows на основе диспетчера виртуальной памяти(Virtual Memory Manager, VMM). API виртуальной памяти Win32 (VirtualAllok, VirtualFree, VirtualLock, VirtualUnlock и т.д.) работает с целыми страницами. API «кучи» Win32 управляет блоками памяти, с объемом определяемым пользователем.

Рисунок 8.1 - Архитектура управления памятью Win32

Разделы адресного пространства. Виртуальное адресное пространство каждого процесса разбивается на разделы. Их размер и назначение в какой-то мере зависят от конкретного ядраWindows (таблица 8.1). Ядра 32- и 64разрядной Windows создают разделы, почти одинаковые по назначению, но отличающиеся по размеру и расположению.

41

Таблица 8.1 Разделы адресного пространства

Раздел

32-

32-разрядная

64-разрядная Windows

64-разрядная

 

разрядная

Windows (на

(на х64)

 

Windows (на IA-64)

 

Windows (на

х86 с клю-

 

 

 

 

х86)

чом /3GB)

 

 

 

Для выявления

0x00000000

0x00000000

0x00000000

00000000

0x00000000 00000000

нулевых указате-

0x0000FFFF

0x0000FFFF

0x00000000

0000FFFF

0x00000000

лей

 

 

 

 

0000FFFF

Для кода и дан-

0x00010000

0x00010000

0x00000000

00010000

0x00000000 00010000

ных пользова-

0x7FFEFFFF

0xBFFEFFFF

0x000007FF FFFEFFFF

0x000006FB

тельского режима

 

 

 

 

FFFEFFFF

Закрытый, разме-

0x7FFF0000

0xBFFF0000

0x000007FF FFFF0000

0x000006FB

ром 64 Кб

0x7FFFFFFF

0xBFFFFFFF

0x000007FF FFFFFFFF

FFFF0000

 

 

 

 

 

0x000006FB

 

 

 

 

 

FFFFFFFF

Для кода и дан-

0x800000000

0xC0000000

0x00000800

00000000

0x000006FC

ных режима ядра

0xFFFFFFFF

0xFFFFFFFF

0xFFFFFFFF FFFFFFFF

00000000

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

Таблица 8.2 Размер и адреса раздела пользовательского режима

Архитектура ЦП

Диапазон адресов размера

Размер раздела пользова-

 

пользовательского режима

тельского режима

х86

0x00010000-0x7FFEFFFF

-2 Гб

х86 (с ключом

0x00010000-0xBFFFFFFF

-3 Гб

/3GB)

 

 

х64

0x00000000’00010000-

-8192 Гб

 

0x000007FF’FFFEFFFF

 

IA-64

0x00000000’00010000-

-7152 Гб

 

0x000006FB’FFFEFFFF

 

Регионы в адресном пространстве. Адресное пространство, выделяемое процессу в момент создания, практически все свободно. Поэтому, чтобы воспользоваться какой-нибудь его частью, нужно выделить в нем определенные регионы через функцию VirtualAlloc. Операция выделения региона называется

резервированием (reserving).

PVOID VirtualAlloc( PVOID pvAddress, SIZE_T dwSize, DWORD fdwAllocationType, DWORD fdwProtect);

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

42

цию: зарезервировать регион или передать физическую память. Для резервиро-

вания MEM_RESERVE.

Для резервирования регион по самым старшим адресам, скомбинировать с флагом MEM_TOP_DOWN. fdwProtect указывает атрибут защиты, присваиваемый региону. Можно использовать любой из следующих атрибутов защиты:

PAGE_NOACCESS, PAGE_READWRITE, PAGE_READONLY, PAGE_EXECUTE, PAGE_EXECUTE_READ или PAGE_ EXECUTE_READWRITE.

Передать физическую память (committing physical storage) функцией VirtualAlloc. В fdwAllocationType задать MEM_COMMIT, pvAddress задать желатель-

ный адрес, а dwSize - размер физической памяти.

Могут применяться флагиPAGE_GUARD, PAGE_WRITECOMBINE или PAGE_NOCACHE

Возврат физической памяти (decommitting physical storage) - выполняется

вызовом функции VirtualFree.

 

BOOL VirtualFree(LPVOID pvAddress,

SIZE_T dwSize,

 

DWORD fdwFreeType);

 

В dwSize можно

передать 0, в (fdwFreeType) идентификатор

MEM_RELEASE; это приведет к возврату системе всей физической памяти, ото-

браженной на регион, и к освобождению самого региона. Для возврата в систему части физической памяти, переданной региону задать вpvAddress адрес, указывающий на первую возвращаемую страницу. dwSize задать количество освобождаемых байтов, а fdwFreeType - идентификатор MEMDE-COMMIT.

Атрибуты защиты страницы памяти можно изменить вызовомVirtualProtect

BOOL VirtualProtect( PVOID pvAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD pflOldProtect);

flNewProtect задает идентификаторы PAGE_*, кроме PAGE_WRITECOPY и PAGE_EXECUTE_WRITECOPY. pflOldProtect содержит адрес переменной типа

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

VirtualProtect(pvRgnBase + (3 * 1024), 2 * 1024, PAGE_NOACCESS, &fl0ldProtect);

то атрибут защиты PAGE_NOACCESS будет присвоен двум страницам памяти. В Windows имеется функция, позволяющая запрашивать определенную

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

DWORD VirtualQuery( LPCVOID pvAddress, PMEMORY_BASIC_INFORMATION pmbi,

DWORD dwLength);

VirtualQueryEx, сообщает ту же информацию о памяти, но в другом процессе:

43

DWORD VirtualQueryEx(

HANDLE hProcess, LPCVOID pvAddress,

PMEMORY_BASIC_INFORMATION pmbi, DWORD dwLength);

Эти функции идентичны с тем исключением, что VirtualQueryEx принимает идентификатор процесса, об адресном пространстве которого вы хотите получить информацию.

Основная литература: 1[155-198], 3[432-455], 5[340-372]

Дополнительная литература: 14[132-134]

Контрольные вопросы:

1.Какие существуют API уровни управления памятью.

2.На какие разделы разбивается адресное пространство.

3.Какой диапазон адресов, и какие размеры раздела применяются.

4.Для каких целей применяется регион в адресном пространстве.

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

Лекция 9. Архитектура памяти. Динамически распределяемая память.

Механизм управления памятьюдинамически распределяемые области памяти, или кучи (heaps).

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

Стандартная куча процесса. При инициализации процесса система создает в его адресном пространстве стандартную кучу(process's default heap), размер по умолчанию - 1 Мб. Система позволяет увеличивать этот размер, для

этого

указать

компоновщику

при

сборке

программы/HEAPключ.

/HEAP:reserve[, commit]

 

 

 

 

Система гарантирует в каждый момент времени выделение или освобож-

 

дение блока памяти только для одного потока в этой куче. У одного процесса

 

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

 

вования. Но стандартная куча процесса создается в начале его исполнения и ав-

 

томатически уничтожается по его завершениисамим уничтожить ее невоз-

 

можно.

Описатель

стандартной

кучи

процесса

возвращает

функци

GetProcessHeap:

HANDLE GetProcessHeap();

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

-защиты компонентов;

-более эффективного управления памятью;

-локального доступа;

44

-исключения издержек, связанных с синхронизацией потоков;

-быстрого освобождения всей памяти в куче.

Создание дополнительной кучи. Дополнительные кучи в процессе создаются вызовом HeapCreate:

HANDLE HeapCreate( DWORD fdwOptions, SIZE_T dwInitialSize, SIZE_T dwMaximumSize);

fdwOptions модифицирует способ выполнения операций над кучей. В нем можно указать 0, НЕАР_NO_SERIALIZE, НЕАР_GENERATE_EXCEPTIONS, HEAP_CREATE_ENABLE_EXECUTE или комбинацию флагов. По умолчанию действует принцип последовательного доступа к куче, что позволяет не опасаться одновременного обращения к ней сразу нескольких потоков.

Флаг HEAP_NO_SERIALIZE используют при выполнении следующих условий:

-в процессе существует лишь один поток;

-в процессе несколько потоков, но с кучей работает лишь один из них;

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

Флаг HEAP_GENERATE_EXCEPTIONS, заставляет систему генерировать исключение при любом провале попытки выделения блока в куче.

Выделение блока памяти из кучи. Для этого достаточно вызвать функ-

цию HeapAlloc:

PVOID HeapAlloc( HANDLE hHeap, DWORD fdwFlags, SIZE_T dwBytes); hHeap идентифицирует описатель кучи, из которой выделяется память. dwBytes определяет число выделяемых в куче байтов/

fdwFlags позволяет указывать флаги, влияющие на характер выделения памяти. В настоящее время поддерживается только :три

HEAP_ZERO_MEMORY, HEAP_GENERATE_EXCEPTIONS и HEAP_NO_SERIALIZE.

HEAP_ZERO_MEMORY приводит к заполнению содержимого блока нулями перед возвратом из HeapAlloc.

HEAP_GENERATE_EXCEPTIONS заставляет функцию генерировать программное исключение, если в куче не хватает памяти для удовлетворения -за проса.

HEAP_NO_SERIALIZE заставляет HeapAlloc при данном вызове не применять принцип последовательного доступа к куче.

Изменение размера блока. Для изменения размера блока памяти вызывается функция HeapReAlloc.

PVOID HeapReAlloc( HANDLE hHeap, DWORD fdwFlags, PVOID pvMem, SIZE_T dwBytes);

fdwHags указывает флаги, используемые при изменении размера блока:

HEAP_GENERATE_EXCEPTIONS, HEAP_NO_SERIALIZE, HEAP_ZERO_MEMORY или HEAP_REALLOCK_IN_PLACE_ONLY. Первые два

45

флага имеют тот же смысл, что и при использовании HeapAllocс . HEAP_ZERO_MEMORY полезен только при увеличении размера блока памяти.

HEAP_REALLOC_IN_PLACE_ONLY сообщает HeapReAlloc, что данный блок памяти перемещать внутри кучи не разрешается. pvMem и dwBytes определяют текущий адрес изменяемого блока и его новый размер (в байтах).

Функция HeapReAlloc возвращает либо адрес нового, измененного блока, либо NULL, если размер блока изменить не удалось.

Определение размера блока. Выделив блок памяти, можно вызвать HeapSize и узнать его истинный размер:

SIZE_T HeapSize( HANDLE hHeap, DWORD fdwFlags, LPCVOID pvMem);

fdwFlags принимает два значения: 0 или HEAP_NO_SERIALIZE.

Освобождение блока. Для этого служит функция HeapFree:

BOOL HeapFree( HANDLE hHeap, DWORD fdwFlags, PVOID pvMem);

Она освобождает блок памяти и при успешном вызове возвращаетTRUE. fdwFtegs принимает два значения: 0 или HEAP_NO_SERIALIZE.

Уничтожение кучи. Кучу можно уничтожить вызовом HeapDestroy:

BOOL HeapDestroy(HANDLE hHeap);

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

Использование куч в программах на C++ . Выделение памяти для объекта класса выполняется вызовом оператора new, создать экземпляр:

CSomeClass* pSomeClass = new CSomeClass;

Созданный объект уничтожается обращением к оператору delete: delete pSomeClass;

Для управления кучей в СРРфайл следует включить код:

HANDLE CSomeClass::s_hHeap = NULL; UINT CSomeClass::s_uNumAllocsInHeap = 0;

void* CSomeClass::operator new (size_t size) { if (s_hHeap== NULL) {

s.hHeap = HeapCreate(HEAP_NO_SERIALIZE, 0, 0); if (s.hHeap == NULL) return(NULL); }

void* p = HeapAlloc(s_hHeap, 0, size); if (p != NULL) { s_uNumAllocsInHeap++; }

return(p); }

Объект разрушается функцией, переопределяющей оператор delete:

void CSomeClass::operator delete (void* p) { if (HeapFree(s_hHeap, 0, p)) { s_uNumAllocsInHeap--; } if (s_uNumAllocsInHeap == 0) { if (HeapDestroy(s_hHeap)) { NULL, new CSomeClass s_hHeap = NULL;} } } }

46

Другие функции управления кучами. Windows имеет несколько функций,

предназначенных для управления кучами. В адресном пространстве процесса может быть несколько куч, и функция GetProcessHeaps позволяет получить их описатели «одним махом»:

DWORD GetProcessHeaps( DWORD dwNumHeaps, PHANDLE phHeaps);

Вызвать функцию так:

HANDLE hHeaps[25]; DWORD dwHeaps = GetProcessHeaps(25, hHeaps); if (dwHeaps > 25) {

} else { hHeaps[0] hHeaps[dwHeaps - 1]

}

Целостность кучи позволяет проверить функция HeapValidate:

BOOL HeapValidate( HANDLE hHeap, DWORD fdwFlags, LPCVOID pvMem);

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

HeapCompact:

UINT HeapCompact( HANDLE hHeap, DWORD fdwFlags);

Две функции - HeapLock и HeapUnlock - используются парно, предназначены для синхронизации потоков:

BOOL HeapLock(HANDLE hHeap); BOOL HeapUnlock(HANDLE hHeap);

Функция HeapWalk используется для работы с кучами:

BOOL HeapWalk( HANDLE hHeap, PPROCESS_HEAP_ENTRY pHeapEn-

try);

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

PROCESS_HEAP__ENTRY.

Резюме по управлению кучей:

1.Получить дескриптор кучи, используя функции Create_Heap либо GetProcessHeap.

2.Распределить блоки из кучи с помощью функции HeapAlloc.

3.При необходимости освободить все или некоторые блоки функцией

HeapFree.

4.Уничтожить кучу и закрыть ее дескриптор функцией HeapDestroy

Основная литература: 1[155-198], 3[598-612]

Дополнительная литература: 15[193-206]

Контрольные вопросы:

1.Что представляет собой механизм управления памятью.

2.Дайте определение понятию «куча», назначение.

3.Объясните назначение «дополнительные кучи», какие флаги применя-

ются.

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

5.Какие функции используются для управления кучами.

47

Лекция 10. Проецируемые в память файлы

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

-загрузки и выполнения EXE- и DLL-файлов;

-доступа к файлу данных, размещенному на диске;

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

Проецирование файлов обеспечивает преимущества:

-нет необходимости выполнять операции непосредственного файлового ввода/вывода;

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

-применения удобных и эффективных алгоритмов работы с файлами«в памяти» (in-memory files) (сортировка, деревья поиска, обработка строк и т.д.), позволяющие обрабатывать данные файла даже в том случае, когда размер данного файла превышает доступный объема физической памяти;

-в некоторых случаях повышается эффективность обработки файлов;

-исключается необходимость в управлении буферами, в манипулировании данными файлов этих буферов, все это обеспечивает сама ОС;

-одна область памяти может быть использована несколькими процессами путем отображения своих виртуальных адресных пространств в один файл или файл подкачки;

-исключается необходимость в расходовании излишнего пространства файла подкачки.

Использование проецируемых в память файлов. Для этого нужно выпол-

нить три операции:

1. Создать или открыть объект ядра «файл», идентифицирующий дисковый файл, который вы хотите использовать как проецируемый в память;

2. Создать объект ядра «проекция файла», чтобы сообщить системе размер файла и способ доступа к нему;

3. Указать системе, как спроецировать в адресное пространство вашего процесса объект «проекция файла» - целиком или частично.

Закончив работу с проецируемым в память файлом, следует выполнить три операции:

1. Сообщить системе об отмене проецирования на адресное пространство процесса объекта ядра «проекция файла»;

2. Закрыть этот объект;

3. Закрыть объект ядра «файл».

Создание или открытие объекта ядра«файл» Используем функцию

CreateFile:

48

HANDLE CreateFile( PCSTR pszFileName, DWORD dwDesiredAccess, DWORD dwShareMode, PSECURITY_ATTRIBUTES psa, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);

pszFileName, идентифицирует имя создаваемого или открываемого файла (при необходимости вместе с путем).

dwDesiredAccess, указывает способ доступа к содержимому файла. Здесь задается одно из четырех значений.

dwShareMode, указывает тип совместного доступа к данному файлу.

Создание объекта ядра«проекция файла». Сообщаем системе, какой объем физической памяти нужен проекции файла, вызвав функцию CreateFileMapping.

HANDLE CreateFileMapping( HANDLE hFile, PSECURITY_ATTRIBUTES psa,

DWORD fdwProtect,

DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, PCTSTR pszName);

hFile, идентификатор файла, проецируемого на адресное пространство процесса, получен после вызоваCreateFile. psa - указатель на структуру SECURITY_ATTRIBUTES, которая относится к объекту ядра«проекция файла»; для установки защиты по умолчанию ему присваиваетсяNULL. При создании объекта «проекция файла» система не резервирует регион адресного пространства и не увязывает его с физической памятью из файла. В fdwProtect указать желательные атрибуты защиты.

PAGE_READONLY. Можно считывать данные из файла. При этом необхо-

димо передать в CreateFile флаг GENERIC_READ.

PAGE_READWRITE. Можно считывать данные из файла и записывать их. При этом необходимо передатьCreateFileв комбинацию флагов

GENERIC_READ | GENERIC_WRITE

PAGE_WRITECOPY. Можно считывать данные из файла и записывать их. Запись приведет к созданию закрытой копии страницы. При этом необходимо

передать в CreateFile либо GENERIC_READ, либо GENERIC_READ

|

GENERIC_WRITE PAGE_EXECUTE_READ. Можно считывать данные файла,

а

также запускать файл. При этом необходимо передать в CreateFile комбинацию флагов GENERIC_ READ и GENERIC_EXECUTE.

PAGE_EXECUTE_READWRITE. Можно считывать данные из файла, записывать их, а также запускать файл. При этом необходимо передать в CreateFile

комбинацию

флагов GENERIC_READ,

GE-NERIC_WRITE

и

GENERIC_EXECUTE.

 

в параметрfdwProtect функции

Четыре атрибута

раздела можно ввести

Create FileMapping побитовой операцией OR. Раздел (section) - всего лишь еще одно название проекции памяти, отображаемое программой Process Explorer от

49

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

Второй атрибут, SEC_IMAGE, указывает системе, что данный файл является переносимым исполняемым файлом (portable executable, РЕ). Система определяет, какие атрибуты защиты следует присвоить различным страницам проецируемого образа (mapped image). Атрибут SEC_IMAGE заставляет систему спроецировать образ файла и автоматически подобрать подходящие атрибуты защиты страниц. Последний атрибут, SEC_LARGE_PAGES, приказывает Windows использовать большие страницы для проецирования в память файлов образов.

Параметры dwMaximumSizeHigh и dwMaximumSizeLow самые важные. Ос-

новное назначение CreateFileMapping - гарантировать, что объекту «проекция файла» доступен нужный объем физической памяти. Через эти параметры системе объявляется максимальный размер файла в байтах.

pszName - строка с нулевым байтом в конце; в ней указывается имя объекта «проекция файла», которое используется для доступа к данному объекту из другого процесса.

Проецирование файловых данных на адресное пространство процесса.

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

PVOID MapViewOfFile( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap);

Параметр hFileMappingObject идентифицирует описатель объекта «проекция файла», возвращаемый предшествующим вызовом либо CreateFileMapping, либо OpenFileMapping. Параметр dwDesiredAccess идентифицирует вид доступа к данным. Можно задать одно из четырех значений.

FILE_MAP_WRITE. Данные можно считывать и записывать; необходимо

передать

функции CreateFileMapping

атрибут

PAGE_READWRITE

FILE_MAP_READ.

Данные

можно

только считывать; необходимо вызвать

CreateFileMapping

с любым

из следующих

атрибутов: PAGE_READONLY,

PAGE_ READWRITE или PAGE_WRITECOPY

 

 

 

FILE_MAP_ALL_ACCESS.

То

же,

что

и

FILE_MAP_WRITE

FILE_MAP_COPY. Данные можно считывать и записывать, но запись приводит к созданию закрытой копии страницы; необходимо вызвать CreateFileMapping с любым из следующих атрибутов: PAGE_READONLY, PAGE_READWRITE или

PAGE_WRITECOPY.

FILE_MAP_EXECUTE. Содержимое файла может быть исполнено как код;

необходимо

вызвать CreateFileMapping

с

атрибутом

PAGE_EXECUTE_READWRITE или PAGE_EXECUTE_READ.

 

Три параметра относятся к резервированию региона адресного простран-

ства и к

отображению на него физической

. памятиdwFileOffsetHigh и

50

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

Отключение файла данных от адресного пространства процесса.

Освобождение региона выполняется вызовом:

BOOL UnmapViewOfFile(PVOID pvBaseAddress);

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

BOOL FlushViewOfFile( PVOID pvAddress, SIZE_T dwNumberOfBytesToFlush);

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

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

Закрытие объектов «проекция файла» и «файл» Для закрытия объектов

«проекция файла» и «файл» дважды вызвать функцию CloseHandle.

HANDLE hFile = CreateFile(…); HANDLE hFileMapping = CreateFileMapping(hFile, …); CloseHandle(hFile); PVOID pvFile = MapViewOfFile(hFileMapping, …); CloseHandle(hFileMapping); UnmapViewOfFile(pvFile);

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

MapViewOfFile нужна MapViewOfFileEx:

PVOID MapViewOfFileEx( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap, PVOID pvBaseAddress);

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

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

51

При вызове MapViewOfFileEx следует указывать адрес в границах пользовательского раздела адресного пространства процесса, иначе функция вернет

NULL.

Основная литература: 1[155-198], 3[409-461, 536-598]

Дополнительная литература: 14[145-158]

Контрольные вопросы:

1.Объясните назначение процесса проецирования в память файлов.

2.Какие преимущества обеспечивает проецирование файлов.

3.Каков порядок выполнения операций при проецировании файлов.

4.Какие применяются функции для проецирования файлов.

5.Какие функции предназначены для определения базового адреса проецируемого файла.

Лекция 11. Библиотеки. Динамически подключаемые библиотеки

Динамически подключаемые библиотеки (dynamiclink libraries, DLL) - основа операционной системы Windows. В DLL содержатся все функции Windows API. Три самые важные DLL:

-Kernel32.dll (управление памятью, процессами и потоками);

-User32.dll (поддержка пользовательского интерфейса, в том числе функции, связанные с созданием окон и передачей сообщений);

-GDI32.dll (графика и вывод текста).

В Windows существуют другие DLL, функции которых предназначены для специализированных задач:

-AdvAPI32.dll содержит функции для защиты объектов, работы с реестром

ирегистрации событий;

-ComDlg32.dll - стандартные диалоговые окна (вроде FileOpen и FileSave);

-ComCtl32.dll поддерживает стандартные элементы управления. Основными причинами необходимости применения DLL:

-расширение функциональности приложения;

-экономия памяти;

-разделение ресурсов;

-упрощение локализации;

-решение проблем, связанных с особенностями различных платформ;

-реализация специфических возможностей.

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

52

ресное пространство вызывающего процесса. После этого функцииDLL доступны всем потокам этого процесса. Фактически библиотеки при этом теряют почти всю индивидуальность: для потоков код и данные DLL - просто дополнительные код и данные, оказавшиеся в адресном пространстве процесса. Когда поток вызывает изDLL какую-то функцию, та считывает свои параметры из стека потока и размещает в этом стеке собственные локальные переменные. Кроме того, любые созданные кодом DLL объекты принадлежат вызывающему потоку или процессу - DLL ничем не владеет. Глобальные и статические переменные ЕХЕ-файла не разделяются его параллельно выполняемыми экземплярами.

Неявное связывание (implicit linking) - самый распространенный на сегодняшний день метод.

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

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

При компиляции исходного файлаDLL идентификатор определяется как _declspec(dllexport) до включения заголовочного файла. Идентификатор помещается в заголовочный файл до определения экспортируемой переменной или функции. Компилятор, проанализировав заголовочный файл, запоминает, какие переменные и функции являются экспортируемыми. Идентификатор включает extern. Модификатор extern не дает компилятору искажать имена переменных или функций, и они становятся доступными исполняемым модулям, написанным на С, C++ или любом другом языке программирования.

В исходных файлах ЕХЕ-модуля включая заголовочный файл, определяют идентификатор как _declspec(dllimport), и при компиляции исходного кода ЕХЕ-модуля компилятор поймет, что переменные и функции импортируются из

DLL.

Экспорт. Если модификатор _declspec(dllexport) указан перед переменной, прототипом функции или С++ классом, компилятор Microsoft C/C++ встраивает в конечный OBJ-файл дополнительную информацию. Обнаружив такую информацию, компоновщик создает LIB-файл со списком идентификаторов, экспортируемых из DLL. Компоновщик также вставляет в конечныйDLL-файл

53

таблицу экспортируемых идентификаторов- раздел экспорта, в котором содержится список идентификаторов экспортируемых функций, переменных и классов. Туда же помещаетсяотносительный виртуальный адрес(relative virtual address, RVA) каждого идентификатора внутри DLL-модуля.

Создание ЕХЕ-модуля. Создавая файлы исходного кода дляЕХЕ-модуля, необходимо включить в них заголовочный файлDLL. Идентификатор в исходных файлах ЕХЕ-модуля до заголовочного файла DLL не определяется. Поэтому при компиляции кода идентификатор за счет заголовочного файла будет определен как __declspec (dllimport). Далее компоновщик собирает всеOBJмодули в конечный ЕХЕ-модуль.

Импорт. Импортируя идентификатор, необязательно прибегать к _declspec(dllimport) - можно использовать стандартное ключевое словоextern языка C.

Разрешая ссылки на импортируемые идентификаторы, компоновщик создает в конечном ЕХЕ-модуле раздел импорта (imports section). В нем перечисляются DLL, необходимые этому модулю, и идентификаторы, на которые есть ссылки из всех используемых DLL.

Выполнение ЕХЕ-модуля. При запуске ЕХЕ-файла загрузчик операционной системы создает для его процесса виртуальное адресное пространство и проецирует на него исполняемый модуль. Затем анализирует раздел импорта и пытается спроецировать все необходимыеDLL на адресное пространство процесса. Поиск DLL осуществляется в следующей последовательности.

1.Каталог, содержащий ЕХЕ-файл.

2.Основной каталог Windows (по данным GetWindowsDirectory).

3.Системный каталог Windows (по данным GetSystemDirectory).

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

5.Каталоги, указанные в переменной окружения PATH.

Явная загрузка DLL и связывание идентификаторов. Чтобы поток мог вызвать функцию из DLL-модуля, модуль надо спроецировать на адресное пространство процесса, которому принадлежит этот поток. Два способа. Первый - код приложения просто ссылается на идентификаторы, содержащиеся в DLL, и тем самым заставляет загрузчик неявно загружать(и связывать) нужную DLL при запуске приложения.

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

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

HMODULE LoadLibrary(PCTSTR pszDLLPathName);

HMODULE LoadLibraryEx( PCTSTR pszDLLPathName, HANDLE hFile, DWORD dwFlags);

54

Обе функции ищут образ DLL-файла и пытаются спроецировать его на адресное пространство вызывающего процесса. Значение типа HINSTANCE, возвращаемое этими функциями, сообщает адрес виртуальной памяти, по которому спроецирован образ файла. Параметры функции LoadLibraryEx: hFile и dwFlags. Первый зарезервирован для использования в будущих версиях и должен быть NULL. Во втором можно передать либо0, либо комбинацию флагов

DONT_RESOLVE_DLL_REFERENCES, LOAD_LIBRARY_ AS_DATAFILE, LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE, LOAD_LIBRARY_ AS_IMAGE_RESOURCE, LOAD_WITH_ALTERED_SEARCH_PATH и LOAD_IGNORE_CODE_AUTHZ_LEVEL.

Явная выгрузка DLL. DLL можно выгрузить из адресного пространства процесса, вызвав функцию:

BOOL FreeLibrary(HMODULE hInstDll);

В FreeLibrary передать значение типа HWSTANCE, которое идентифицирует выгружаемую DLL. Это значение получим после вызова LoadLibrary(Ex).

DLL можно выгрузить и с помощью другой функции:

VOID FreeLibraryAndExitThread(HMODULE hInstDll, DWORD dwExitCode);

Она реализована в Kernel32.dll так:

VOID FreeLibraryAndExitThread(HMODULE hInstDll,

DWORD dwExitCode) { FreeLibrary(hInstDll);ExitThread(dwExitCode);}

Чтобы определить, спроецирована ли DLL на адресное пространство процесса, поток может вызвать функцию GetModuleHandle:

HMODULE GetModuleHandle(PCTSTR pszModuleName);

Если у вас есть значение HINSTANCE/HMODULE для DLL, можно определить полное (вместе с путем) имя DLL или EXE с помощью GetModuleFileName:

DWORD GetModuleFileName( HMODULE hInstModule, PTSTR pszPathName, DWORD cchPath);

Явное подключение экспортируемого идентификатора. Поток получает адрес экспортируемого идентификатора из явно загруженнойDLL вызовом

GetProcAddress:

FARPROC GetProcAddress( HMODULE hInstDll, PCSTR pszSymbolName);

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

PFN_DUMPMODULE pfnDumpModule = (PFN_DUMPMODULE) GetProcAddress(hDll, "DumpModule"); if (pfnDumpModule != NULL) {

pfnDumpModule(hDll); }

Функция входа/выхода. В DLL может быть лишь одна функция -вхо да/выхода. Система вызывает ее в некоторых ситуациях в информационных целях, и она используется DLL для инициализации и очистки ресурсов в конкрет-

55

ных процессах или потоках. Если уведомления необходимы, функция должна выглядеть:

BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, PVOID fImpLoad) { switch (fdwReason) { case DLL_PROCESS_ATTACH: break; case DLL_THREAD_ATTACH:

break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: break; } return(TRUE);

}

Основная литература: 1[155-198], 3[615-677]

Дополнительная литература: 14[158-166]

Контрольные вопросы

1.Какие библиотеки применяются в Windows.

2.Как связано адресное пространство с DLL.

3.Что представляет собой явное и неявное связывание.

4.Как создаются и выполняются DLL- и EXEмодули.

5.Что предполагает связывание идентификаторов.

6.Какие функции входа/выхода в DLL.

Лекция 12 . Ввод вывод. Взаимодействие между процессами.

Основными механизмамиWindows реализующими межпроцессное взаимодействие (Interprocess Communication, IPC) являются анонимные и именованные каналы. Доступ к каналам осуществляется с помощью функцийReadFile и WriteFile.

Анонимные каналы (anonymous channels). Каждый канал имеет два дескриптора: чтения (read handle) и записи (write handle). Прототип функции создания анонимного канала:

BOOL CreatePipe (

PHANDLE phRead, PHANDLE phWrite, PSECURITY_ATTRIBUTES lpsa, DWORD cbPipe)

cbPipe - размер канала в байтах, по умолчанию соответствует 0. В случае использования канала для IPC должен существовать еще один процесс, с которым будет связан какой либо дескриптор канала. Если канал пуст, то чтение с использованием дескриптора чтения канала блокируется. Иначе в процессе чтения будет принято столько байтов, сколько имеется в канале, но не больше величины указанной при вызове функции ReadFile. Запись выполняется с использованием буфера, если канал заполненный, то также будет блокирована.

Именованные каналы (named pipes). Это универсальный механизм реализации приложений на основе IPC, включая приложения, требующие сетевого доступа к файлам, клиент-серверные системы. Дополнительные возможности:

-именованные каналы ориентированы на обмен сообщениями;

-именованные каналы являются двунаправленными;

56

-возможны несколько независимых экземпляров канала с одинаковыми именами;

-используя имя канала к нему может обратиться любая из систем, подключенная к сети;

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

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

Создание именованных каналов.

HANDLE CreateNamedPipe ( PCTSTR lpName,

DWORD dwOpenMode, DWORD dwPipeMode, DWORD nMaxInstances, DWORD nOutBufferSize, DWORD nInBufferSize,

DWORD nDefaultTimeOut, PSECURITY_ATTRIBUTES lpsa)

lpName указатель на имя канала, имеющий вид:\\.\pipe\[path]pipename.

Точка (.) означает локальный компьютер, поэтому канал на удаленном компьютере создать нельзя.

dwOpenMode указывает на один из флагов:

PIPE_ACCESS_DUPLEX - эквивалентен комбинации значенийGENERIC_READ и GENERIC_WRITE.

PIPE_ACCESS_INBOUND - данные передаются в направлении от клиента к серверу, эквивалентно GENERIC_READ.

PIPE_ACCESS_OUTBAND - эквивалентно флагу GENERIC_WRITE.

При задании режима могут быть заданы значенияFILE_FLAG_WRITE и FILE_FLAG_OVERLAPPED.

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

PIPE_TYPE_BYTE и PIPE_TIPE_MESSAGE - запись в канал выполняется как поток байтов или как сообщения

PIPE_READMODE_BYTE и PIPE_READMODE_MESSAGE - считывание данных выполняется как поток байтов или как сообщения. Дл значения

PIPE_READMODE_MESSAGE требуется PIPE_TIPE_MESSAGE. PIPE_WAIT и PIPE_NOWAIT - блокируется или нет операция ReadFile.

nMaxInstances - определяет количество экземпляров каналов, и одновре-

менно

поддерживаемых

.

клиентовЕсли

указать

PIPE_UNLIMITED_INSTANCES, то ОС самостоятельно определит

значение

этого параметра.

 

 

 

 

57

NOutBufferSize и nInBufferSize - задают размеры выходного и входного буферов именованных каналов в байтах.

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

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

Подключение клиентов именованных каналов. Для подключения клиента к именованному каналу применяется функция CreateFile, при ее вызове указывается имя именованного канала. Часто клиент и сервер выполняются на одной

машине и для указания имени канала применяется : форма \\.\pipe\[path]pipename. Если сервер находится на другой машине, для указания имени канала используется форма вида: \\servername\pipe\[path]pipename.

Функции состояния именованных каналов.

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

SetNamedPipeHandleState устанавливает атрибуты состояния. GetNamedPipeInfo определяет принадлежность дескриптора экземпляру

клиента или сервера, размеры буферов и т.д.

Функции подключения именованных каналов. После создания именован-

ного канала сервер может ожидать подключения клиента(с помощью функций

CreateFile и CallNamedPipe), используя функцию ConnectNamedPipe.

BOOL ConnectNamedPipe ( HANDLE hNamePipe, LPOVERLAPPED lpo)

При установке NULL функция ConnectNamedPipe выполняет возврат сразу после соединения с клиентом. При успешном выполнении функции возвращаемое значение будетTRUE. FALSE будет в случае если подключение клиента происходит между вызовами сервером функцийCreateNamedPipe и ConnectNamedPipe. В этот момент функцияGet_Last_Error вернет значение ERROR_PIPE_CONNECTED.

После возврата из функцииConnectNamedPipe сервер сможет считывать запросы с помощью функцииReadFile, и записывать ответы, используя WriteFile. Чтобы освободить дескриптор (экземпляра канала) для соединения с другим клиентом сервер должен вызвать функциюDisconnectNamedPipe. WaitNamedPipe используется клиентами для синхронизации соединений с сервером. Успешный возврат будет в том случае, когда на сервере имеется незавершенный вызов функции ConnectNamedPipe, указывающий на наличие доступного экземпляра именованного канала. Используя WaitNamedPipe, клиент может

58

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

Подключение клиентов и серверов именованных каналов. В последова-

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

сдругим клиентом.

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

Функции транзакций именованных каналов. Последовательность вызо-

вов функций ReadFile и WriteFile можно рассматривать как единую клиентскую транзакцию. Windows предоставляет функцию для каналов сообщений.

BOOL TransactNamedPipe ( HANDLE hNamedPipe,

LPVOID lpWriteBuf, DWORD cbWriteBuf, LPVOID lpReadBuf, DWORD cbReadBuf, LPDWORD lpcbRead, LPOVERLAPPED lpo)

Так как данная функция сочетает в себе функцииReadFile и WriteFile, применяемые к дескриптору именованного канала, значения параметров уже знакомы. Указываются как входной, так и выходной буферы, указатель lpcbRead задает длину сообщения. Функция TransactNamedPipe удобна в использовании, но постоянно требует соединения, а это ограничивает число клиентов.

Функция CallNamedPipe не требует постоянного соединения, а создает временное соединение и объединяет в себе выполнение последовательности операций: CreateFile, WriteFile, ReadFile, CloseHandle

BOOL CallNamedPipe ( PCTSTR lpPipeName,

LPVOID lpWriteBuf, DWORD cbWriteBuf, LPVOID lpReadBuf, DWORD cbReadBuf, LPDWORD lpcbRead, DWORD dwTimeOut)

Используемые параметры аналогичны как и у функции TransactNamedPipe, за исключением того что вместо дескриптора для указания канала используется его имя. Функция выполняется в синхронном режиме. Длительность периода ожидания относится к соединению, а не к транзакции.

dwTimeOut имеет три : значенияNMPWAIT_NOWAI; NMPWAIT_WAIT_FOREVER; NMPWAIT_USE_DEFAULT_WAIT, задает интер-

вал ожидания по умолчанию, заданного в функции CreateNamedPipe.

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

59

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

BOOL PeekNamedPipe ( HANDLE hPipe,

LPVOID lpBuffer, DWORD cbBuffer, LPDWORD lpcbRead, LPDWORD lpcbAvail, LPDWORD lpcbMessage)

Для определения наличия данных в канале нужно проверить значение lpcbAvail, если данные присутствуют, то оно должно быть больше0. В этом случае значения lpBuffer и lpcbRead, могут быть NULL. Если буфер определен параметрами lpBuffer, cbBuffer, то значение lpcbMessage укажет на некоторое количество байтов сообщений, не уместившихся в буфере. Функция выполняет чтение из именованного канала, не уничтожая данные, поэтому для удаления сообщений или байтовых данных из канала, необходимо последующее применение функции ReadFile.

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

При использовании почтовых ящиков выполняются операции:

-каждый сервер создает дескриптор почтового ящика с помощью функции

CreateMailSlot;

-сервер ожидает получения почтового сообщения, используя функцию

ReadFile;

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

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

В вызове функции клиент может указать имя почтового ящика в :виде \\*\mailslot\mailslotname. «*» действует в качестве группового символа(wildcard) и клиент может обнаружить любой сервере в пределахимени домена – группы систем, объединенных общим именем, назначенное администратором сети.

Создание и открытие почтового ящика. Для создания почтового ящика

иполучения дескриптора, который можно использовать в операцияхReadFile почтовые серверы вызывают функцию CreateMailslot

HANDLE CreateMailslot (PCTSTR pszName, DWORD cbMaxMsg, DWORD dwReadTimeout, PSECURITY_ATTRIBUTES lpsa)

pszName - указывает на имя почтового ящика в

\\.\mailslot\[путь]имя.

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

60

dwReadTimeout - длительность интервала ожидания для операции чтения. Значение 0 соответствует немедленному возврату, значение MAILSLOT_WAIT_FOREVER - неопределенный период ожидания(может длиться долго).

Клиент в заключение должен указать флаг FILE_SHARE_READ.

Функции GetMailslotInfo и SetMailslotInfo похожи на свои аналоги, работающие с именованными каналами.

Основная литература: 1[363-394]

Дополнительная литература: 14[46-52, 286-306, 359-386]

Контрольные вопросы:

1.Какие механизмы Windows реализуют межроцессное взаимодействие.

2.В чем различие между анонимными и именованными каналами.

3.Каким образом создаются именованные каналы.

4.Как создаются анонимные каналы.

5.Каким образом можно определить наличие сообщений в именованном

канале.

6.Как выполняются клиентские транзакции.

7.Объясните назначение широковещательного механизма.

Лекция 13. Структурная обработка исключений

Механизм структурной обработки исключений используется с целью ор-

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

Преимущество структурной обработки исключений(structured exception handling, SEH) в том, что при написании кода можно сосредоточиться на решении своей задачи. Основная нагрузка по поддержкеSEH ложится на компилятор, а не на операционную систему. Он генерирует специальный код на входах и выходах блоков исключений(exception blocks), создает таблицы вспомогательных структур данных для поддержкиSEH и предоставляет функции обратного вызова, к которым система могла бы обращаться для прохода по блокам исключений. Компилятор отвечает и за формирование стековых фреймов(stack frames) и другой внутренней информации, используемой операционной системой. SEH предоставляет две основные возможности: обработку исключений

(exception handling) и обработку завершения (termination handling).

Фильтры и обработчики исключений. Исключением называется собы-

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

61

(hardware exception). Операционная система и прикладные программы способны возбуждать собственные исключения- программные (software exceptions). При возникновении аппаратного или программного исключения операционная система дает приложению шанс определить его тип и самостоятельно обработать.

Синтаксис обработчика исключений таков:

_try { …

} _except (exception filter) { … }

_try и _except – ключевые слова распознаваемые компилятором.

Блок _try является частью обычного кода приложения. Если на данном участке кода возникает исключение, ОС передает управление обработчику исключений, блоку кода следующий, за ключевым словом _except. Характер последующих действий определяется значением параметраexception filter (выражение фильтра).

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

Таблица 13.1 Значения, возвращаемые фильтром исключений

Идентификатор

Значение

EXCEPTION_EXECUTE_HANDLER

1

EXCEPTION_CONTINUE_SEARCH

0

EXCEPTION_CONTINUE_EXECUTION

1

Функция GetExceptionCode. Фильтр исключений должен проанализировать ситуацию, прежде чем определить, какое значение ему вернуть. Фильтр отвечает за анализ ситуации и возврат соответствующего значения. Этот фрагмент иллюстрирует метод, позволяющий определять тип исключения:

Встраиваемая функция GetExceptionCode возвращает идентификатор типа исключения:

DWORD GetExceptionCode();

Код исключения должен быть получен сразу же после возникновения -ис ключения. Поэтому функция фильтра не может просто вызвать функцию GetExceptionCode. Эта функция вызывается в выражении фильтра, в котором

код исключения является аргументом функции фильтра, предоставленной пользователем:

_except (MyFilter (GetExceptionCode())){

}

62

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

Встраиваемую функцию GetExceptionCode можно вызвать только из фильтра исключений (между скобками, которые следуют за except) или из обработчика исключений.

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

компилировать код.

 

 

Функция GetExceptionInformation, может

использоваться

при вызове

только из выражения фильтра и возвращает

дополнительную

информацию, в

том числе специфичную для используемого процессора. Когда возникает исключение, операционная система заталкивает в стек соответствующего потока структуры EXCEPTION_RECORD, CONTEXT и EXCEPTION_ POINTERS.

EXCEPTION_RECORD содержит информацию об исключении, независимую от типа процессора, а CONTEXT - машинно-зависимую информацию об этом исключении. В структуре EXCEPTION_POWTERS всего два элементауказатели на помещенные в стек структурыEXCEPTION_ RECORD и CONTEXT:

typedefStruct _EXCEPTION_P0INTERS { PEXCEPTION_RECORD ExceptionRecord; PCONTEXT ContextRecord; } EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;

Чтобы получить эту информацию и использовать ее в программе, вызвать

GetExceptionInformation:

PEXCEPTION_POINTERS GetExceptionInformation();

Эта встраиваемая функция возвращает указатель на структуруEXCEP-

TION_POINTERS.

 

 

 

Структура EXCEPTION_RECORD

содержит

подробную

машинно-

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

-ExceptionCode - код исключения. Это информация, возвращаемая функ-

цией GetExceptionCode.

-ExceptionFlags - флаги исключения. На данный момент определено толь-

ко

два

значения: 0 (возобновляемое

исключение) и

EXCEP-

TION_NONCONTINUABLE (невозобновляемое

исключение). Любая

попытка

возобновить работу программы после невозобновляемого исключения генери-

рует исключение EXCEPTION_NONCONTINUABLE_EXCEPTION.

-ExceptionRecord - указатель на структуру EXCEPTION_RECORD, содер-

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

-ExceptionAddress - адрес машинной команды, при выполнении которой произошло исключение.

63

-NumberParameters - количество параметров, связанных с исключением (0-15). Это число заполненных элементов в Массиве ExceptionInformation. Почти для всех исключений значение этого элемента равно 0.

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

Элемент ContextRecord структуры EXCEPTION_POTNTERS указывает на структуру CONTEXT, содержимое которой зависит от типа процессора. С помощью этой структуры, в основном содержащей по одному элементу для каждого регистра процессора, можно получить дополнительную информацию о возникшем исключении. Структуры CONTEXT для различных процессоров, поддерживаемых Windows, определены в заголовочном файле WinNT.h.

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

VOID RaiseException(DWORD dwExceptionCode, DWORD dwExceptionFlags, DWORD nNumberOfArguments, CONST ULONG_PTR *pArguments);

dwExceptionCode - значение, которое идентифицирует генерируемое ис-

ключение. HeapAlloc передает в нем STATUS_NO_MEMORY, dwExceptionFlags -

должен быть либо 0, либо EXCEPTION_NONCONTINUABLE. В принципе этот флаг указывает, может ли фильтр исключений вернутьEXCEPTION_ CONTINUE_EXECUTION в ответ на данное исключение. Если вы передаете в этом параметре нулевое значение, фильтр может вернутьEXCEPTION_ CONTINUE_EXECUTION.

nNumberOfArguments и pArguments позволяют передать дополнительные данные о генерируемом исключении. Обычно это не нужно, и в pArguments пе-

редается

NULL;

тогда

RaiseException

игнорирует

параметр

nNumberOfArguments.

Если

передаются

дополнительные

аргументы,

nNumberOfArguments

должен

содержать число

элементов в

массиве типа

ULONG_PTR, на который указывает pArguments.

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

_try {.

. } _finally {

... }

64

Ключевые слова _try и _finally обозначают два блока обработчика завершения.

Выход из _try-блока. Обработчик завершения выполняется каждый раз, когда по логике программы осуществляется выход из _try-блока по причине:

-достигнут конец _try-блока и «проваливание» в обработчик завершения;

-локальная раскрутка - преждевременный выход из блока _try при выполнении одного из операторов происходит выход за пределы блока: return, break, goto, longjmp, continue, _leave, вызывающий принудительную передачу управления блоку finally;

-исключение.

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

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

BOOL AbnormalTermination();

Выполнение обработчика завершения и выход из него. Обработчик за-

вершения выполняется в контексте блока или функции, которую он контролирует. Управление может переходить от оператора завершения к следующему оператору. Либо когда обработчик завершения выполняет оператор передачи управления (return, break, goto, longjmp, continue, _leave), либо по причине воз-

никновения исключения.

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

-упрощается обработка ошибок - очистка гарантируется и проводится в одном месте;

-улучшается восприятие текста программ;

-облегчается сопровождение кода.

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

Основная литература: 1[126-153], 3[747-795]

Дополнительная литература: 14[90-111]

Контрольные вопросы:

1. Объясните назначение механизма структурной обработки исключений.

2. В чем заключается преимущество применения структурной обработки исключений.

3. Назовите виды исключений.

4. каков синтаксис обработчика исключений.

5. Как классифицируются исключения.

6. Какие структуры применяются в обработчике исключений.

65

Лекция 14. Система информационной безопасности. Модель безопас-

ности в Windows.

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

Общая задача безопасности системы:

-начальное состояние системы безопасное;

-правила управления доступом обеспечивают переход из безопасного состояния системы в безопасное состояние системы;

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

Модель безопасности в Window. В операционных системах Windows реализована дискреционная модель безопасности. В качестве активных субъектов этой модели безопасности рассматриваются процессы и потоки, каждый из которых работает от имени некоторого пользователя. При регистрации пользователя и входе в систему, для него создается маркер доступа (access token), идентифицирующий этого пользователя и содержащий его привилегии. Каждый процесс, исполняемый от имени пользователя, имеет маркер доступа этого пользователя. Маркер доступа используется для контроля доступа процесса к объектам, которые называются в Windows охраняемыми объектами (securable objects). К охраняемым объектам относятся все объектыWindows, которые могут иметь имя. Кроме того, к охраняемым объектам относятся также потоки и процессы. Каждый охраняемый объект имеет дескриптор безопасности (security descriptor), который создается вместе с охраняемым объектом и содержит информацию, необходимую для защиты объекта от несанкционированного доступа. В дескрипторе безопасности идентифицируется владелец объекта, определяются пользователи и группы пользователей, которым разрешен или запрещен доступ к охраняемому объекту, а также информация для аудита доступа к объекту. Изменять информацию, заданную в дескрипторе безопасности, может только владелец объекта, которым по умолчанию является создатель этого объекта. При доступе к охраняемому объекту система сверяет информацию о пользователе, заданную в маркере доступа, с информацией, заданной в дескрипторе безопасности.

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

Для хранения информации о пользователях, которым разрешен или запрещен доступ к охраняемым объектам, каждый дескриптор безопасности содержит список управления дискреционным доступом(Discretionary AccessControl List, DACL). Для управления аудитом доступа к объекту в дескрипторе безопасности хранится список управления системным доступом(System Access-Control List, SACL). Общее название для этих списковсписки управления доступом

(AccessControl Lists) или сокращенно ACL.

66

Идентификаторы безопасности. Для каждой учетной записи операционная система создает идентификатор безопасности(Security Identifier, SID), который хранится в базе данных менеджера учетных записейSAM. Идентификатор безопасности является бинарным представлением учетной записи и -ис пользуется системой безопасности при своей работе для идентификации учетных записей. Фактически идентификатор безопасности идентифицирует пользователя на уровне системы безопасности. Использование идентификатора безопасности ускоряет работу системы безопасности, т. к. в этом случае система при идентификации пользователей работает с числовыми, а не символьными данными.

Символически структура идентификатора безопасности может быть описана следующим образом:

S - R - I - SAo - SAi - SA2 -SA3 - SA4 ...

Предопределенные значения уровней авторизации учетных записей приведены в таблице 14.1.

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

Вобщем случае количество битовых полей типаsa в идентификаторе безопасности может быть произвольным.

S - R - I - SAo - SAi - SA2 -SA3 - SA4

Такие идентификаторы безопасности создаются для пользователей и групп.

Идентификаторы безопасности предопределенных групп обычно имеют следующую структуру (таблица 14.2.):

S - R - I - SAo

Таблица 14.1

Предопределенные универсальные SID

Предопределенные

Символьное

Уровень авторизации учетной записи

универсальные SID

значение

 

Null SID

S-1-0-0

Группа без членов

World

S-1-1-0

Группа, которая включает всех пользователей

Local

S-1-2-0

Локальные пользователи системы

Creator Owner ID

S-1-3-0

Идентификатор безопасности владельца объекта

Creator Group ID

S-1-3-1

Идентификатор безопасности группы, которой принад-

 

 

лежит владелец объекта

Таблица 14.2 Предопределенные значения типа учетной записи

Идентификаторы учетной записи

Значение

Префикс SID

SECURITY_NULL_SID_AUTHORITY

0

 

S-1-0

67

SECURITY_WORLD_SID_AUTHORITY

1

S-1-1

SECURITY_LOCAL_SID_AUTHORITY

2

S-1-2

SECURITY_CREATOR_SID_AUTHORITY

3

S-1-3

SECURITY NT AUTHORITY

5

S-1-5

 

 

 

Дескрипторы безопасности. Каждый охраняемый объект имеет дескриптор безопасности (security descriptor) или сокращенноSD, который создается вместе с охраняемым объектом и содержит информацию, необходимую для защиты объекта от несанкционированного доступа. Дескриптор безопасности включает заголовок (header), который содержит управляющие флаги и указатели на следующие компоненты:

-SID владельца объекта;

-SID первичной группы владельца объекта;

-указатель на список управления дискреционным доступом - DACL;

-указатель на список управления системным доступом - SACL. Идентификаторы безопасности владельца объекта и первичной группы,

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

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

Списки управления доступом ACL. Список управления доступом(ACL)

содержит элементы, которые называются входами управления доступом (AccessControl Entries, АСЕ). Каждый элемент АСЕ содержит следующую информацию:

-идентификатор безопасности субъекта, которому разрешен или запрещен доступ к охраняемому объекту;

-маску доступа, которая специфицирует права доступа субъекта к охраняемому объекту;

-флаг, который определяет тип элемента АСЕ;

-флаги, которые определяют свойства наследования данного элемента

АСЕ;

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

от имени которого выступает субъект.

Маска доступа представляет собой 32-битовое поле, в котором каждый бит специфицирует определенное право доступа субъекта к охраняемому объекту. Каждое право доступа представляет собой набор операций, которые субъекту разрешается или запрещается выполнять над охраняемым объектом. В Windows права доступа также называются разрешениями(permissions). В операционных системах Windows NT определены следующие четыре категории прав доступа:

- Specific Access Rigths - специфические права доступа;

68

-Standard Access Rights - стандартные права доступа;

-Generic Access Rights - родовые права доступа;

-SACL Access Right - право доступа к списку управления системным доступом (SACL);

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

-read_control - право читать информацию из дескриптора безопасности объекта, за исключением информации из списка SACL;

-write_dac - право модифицировать список DACL в дескрипторе безопасности охраняемого объекта;

-write_owner - право изменить владельца объекта в дескрипторе безопасности охраняемого объекта;

-delete - право удалять охраняемый объект;

-synchronize - право использовать объект для синхронизации.

Родовые права включают следующие четыре права:

-generic_read - право читать содержимое объекта;

-generic_read - право записи в объект;

-generic_execute - право исполнения объекта;

-generic_all - объединяет три предыдущих права.

Для списка управления системным доступом(SACL) определено единственное право:

-access_system_security - право доступа к списку SACL дескриптора безопасности.

Элементы списка DACL могут быть двух типов:

-access_allowed_ace - элемент, разрешающий доступ субъекта к охраняемому объекту;

-access_denied_ace - элемент, запрещающий доступ субъекта к охраняемому объекту.

Список SACL может содержать только элементы типа:

-system_audit_ace - элемент списка SACL.

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

-object_inherit_ace - элемент наследуется неконтейнерным дочерним объектом;

-container_inherit_ace - элемент наследуется только контейнерным дочерним объектом;

-no_propagate_inherit_ace - элемент был унаследован от родительского объекта, но флаги object_inherit_ace и container_inherit_ace в элементе сбрасы-

ваются, что отменяет дальнейшее наследование этого элемента;

-inherit_only_ace - отмечает, что элемент был унаследован от родительского объекта; этот элемент не участвует в контроле доступа к объекту;

69

- inherited_ace - отмечает, что элемент был унаследован от родительского объекта.

Основная литература: 1[483-509] Дополнительная литература: 14[112-131]

Контрольные вопросы:

1.Какая модель безопасности применяется в Windows.

2.Объясните понятие идентификатор безопасности.

3.Как можно описать структуру идентификатора безопасности.

4.Объясните понятие дескриптор безопасности.

5.Какая информация содержится в дескрипторе безопасности.

6.Какие элементы содержит список управления доступом.

Лекция 15. Структура системы безопасности ОС Windows

На рисунке 15.1 приведена общая схема взаимодействия основных компонент системы безопасности операционных систем Windows.

Ключи реестра, в которых хранятся базы данных системы безопасности:

- Local Security Authority Policy Database (HKEY_LOCAL_MACHINE\ SECURITY) - защищенная база данных, в которой хранятся данные, определяющие политику безопасности на локальной машине;

Рисунок 15.1 - Схема взаимодействия компонент системы безопасности

- Security Accounts Database (HKEY_LOCAL_MACHINE\SAM) - защищенная база данных, в которой хранятся учетные записи пользователей и групп, а также связанная с ними информация, такая как, например, пароли и идентификаторы безопасности.

70

Основные программные компоненты системы безопасности:

-Security Reference Monitor (компонент NTOSKRNL.EXE) является компо-

нентом ядра операционной системы и работает в защищенном режиме(режиме ядра);

-Local Security Authority (компонент LSASS.EXE) - определяет, может ли пользователь войти в систему;

-Security Accounts Manager (компонент LSASS.EXE) - является компонен-

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

пасности:

-Winlogon (WINLOGON.EXE) - запускается во время загрузки;

-Authentication Package (MSV1_0.DLL) - используется для верификации полномочий пользователя при доступе субъектов к объектам;

-Netlogon (SERVICES.EXE) - контролирует вход в сеть, обеспечивает безопасную передачу данных о пользователе контроллеру домена.

Управление пользователями. Создание учетной записи пользователя.

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

NET_API_STATUS NetUserAdd ( LPCWSTR servername,

DWORD level, LPBYTE buf, LPDWORD parm_err );

Структура user_info_i, имеет следующий тип: typedef struct _USER_INFO_I {

LPWSTR usril name; LPWSTR usril password; DWORD usril_password_age; DWORD usril priv;

LPWSTR usril_home_dir ; LPWSTR usril_comment ; DWORD usril_flags; LPWSTR usril_script_path;

}USER_INFO_I, *PUSER_INFO_I, *LPUSER_INFO_I;

Получение информации о пользователе. Для получения информации о пользователе из его учетной записи используется функция NetuserGetinfо, которая имеет следующий прототип:

NET_API_STATUS NetUserGetinfо( LPCWSTR servername,

LPCWSTR username, DWORD level, LPBYTE *bufptr

71

);

Для освобождения памяти, которая резервируется функциями из библиотеки netapi32.1ib, используется функция NetApiBufferFree, которая имеет следующий прототип:

NET_API_STATUS NetApiBufferFree ( LPVOID buffer

);

Структура идентификатора безопасности. Идентификатор безопасно-

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

typedef struct _SID { BYTE Revision;

BYTE SubAuthorityCount; SID_IDENTIFIER_AUTHORITY IdentifierAuthority; DWORD SubAuthority[ANYSIZE_ARRAY]; } SID;

Идентификатор безопасности должен содержать идентификатор учетной записи, который хранится в поле IdentifierAuthority, и хотя бы один относительный идентификатор учетной записи.

Идентификатор учетной записи, который определяет ее уровень авторизации или, другими словами, принадлежность учетной записи какому-то множеству учетных записей, задается структурой типа:

typedef struct _SID_IDENTIFIER_AUTHORITY { BYTE Value[6];

} SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY;

В операционных системах Windows предопределены следующие идентификаторы безопасности:

-SECURITY_NULL_SID_AUTHORITY - 0;

-SECURITY_WORLD_SID_AUTHORITY - 1;

-SECURITY_LOCAL_SID_AUTHORITY - 2;

-SECURITY_CREATOR_SID_AUTHORITY - 3;

-SECURITY_NON_UNIQUE_AUTHORITY - 4;

-SECURITY_NT_AUTHORITY - 5.

Создание идентификатора безопасности. Для определения длины буфе-

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

DWORD GetSidLengthRequired(

UCHAR nSubAuthorityCount);

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

72

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

BOOL InitializeSid( PSID pSid,

PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority, BYTE nSubAuthorityCount);

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

PDWORD GetSidSubAuthority( PSID pSid,

DWORD nSubAuthority );

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

BOOL AllocateAndInitializeSid ( PSID_IDENTIFIER_AUTHORITY pidentifierAuthority, BYTE nSubAuthorityCount,

DWORD nSubAuthority0,

DWORD nSubAuthority1,

DWORD nSubAuthority2,

DWORD nSubAuthority3,

DWORD nSubAuthority4,

DWORD nSubAuthority5,

DWORD nSubAuthority6,

DWORD nSubAuthority7, PSID *pSid

);

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

PVOID FreeSid( PSID pSid

);

Определение учетной записи по идентификатору безопасности. Для определения имени учетной записи по ее идентификатору безопасностиис пользуется функция LookupAccountsid, которая имеет следующий прототип:

BOOL LookupAccountsid(

LPCSTR IpSystemName, PSID pSid,

LPSTR lpName, LPDWORD cbName,

LPSTR ReferencedDomainName,

73

LPDWORD cbReferencedDomainName, PSID_NAME_USE peUse

);

Получение характеристик идентификатора безопасности. Для опре-

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

DWORD GetLengthSid ( PSID pSid

);

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

PSID_IDENTIFIER_AUTHORITY GetSidIdentifierAuthority (PSID pSid);

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

PUCHAR GetSidSubAuthorityCount( PSID pSid

);

Основная литература: 1[483-509] Дополнительная литература: 14[112-131]

Контрольные вопросы

1.Объясните схему взаимодействия компонент системы безопасности.

2.Назовите ключи реестра, в которых хранятся базы данных системы безопасности.

3.Какие вспомогательные процессы участвуют в работе системы безопас-

ности.

4.Какие функции используются при управлении пользователями.

5.Какие структуры применяются в системе безопасности.

6.Какая информация содержится в идентификаторе безопасности.

2. 3 Планы лабораторных занятий

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

Лабораторная работа № 1. Управлением курсором, построение рамки. Задание: Написать программу для вывода рамки заданных размеров в -за

данном месте экрана. Оформить программу построения рамки в виде процедуры. Написать программу для вызова процедуры.

Дополнительная литература: 11[3-69], 13[208-255, 257-270, 318-332]

Контрольные вопросы:

74

1.Что называется процедурой, как записывается процедура, ключевые ко-

манды.

2.Каким образом задаются позиции для установки курсора.

3.В каком виде задаются символы, для вывода рамки.

4.Как можно управлять положением курсора на экране?

5.Как оформить процедуру?

6.Как передать параметры в процедуру?

7.Какие операции требуются для построения рамки из символов псевдографики?

Лабораторная работа № 2. Разработка меню, управление курсором в ме-

ню.

Задание: Написать программу для опроса нажатых клавиш, определения вида нажатой клавиши и передачи управления на соответствующую метку. При нажатии на клавишу«стрелка вверх» – курсор перемещается на одну строку вверх. При нажатии клавиши «стрелка вниз» - курсор перемещается на одну строку вниз. Обеспечить перемещение курсора по меню по кольцевому принципу: при достижении курсором крайней позиции(верхней или нижней) необходимо переходить на противоположную границу. При нажатии клавиши «Enter» - управление должно передаваться на выполнение пункта меню. При нажатии клавиши «Escape» - происходит завершение работы программы.

Дополнительная литература: 11[3-69], 13[208-255, 257-270, 318-332]

Контрольные вопросы:

1.Каким образом обеспечивается движение курсора в меню.

2.Какими командами выполняется опрос нажатых клавиш.

3.Какие команды отвечают за управление движением курсора.

4.Какие коды применяются при выполнении программы.

5.Как достичь «кольцевого» принципа перемещения курсора?

6.Как можно передать управление на программу, обрабатывающую строку меню, на которой стоит курсор?

Лабораторная работа № 3. Разработка интерфейса пользователя. Задание: Изучить необходимые API-функции, классы и функции создания

окон и элементы управления: кнопки, флажки, переключатели, редакторы текстов, списки и т.д.

Основная литература: 2[31-92] Дополнительная литература: 11[3-69], 16[5-86]

Контрольные вопросы:

1.Какие API-функции использовались при работе с программой.

2.Какие аргументы используются в функциях, применяемых в программе.

3.Как выполняется цикл обработки сообщений.

4.Какие включает API-функции цикл обработки сообщений

75

5. Как происходит обработка сообщения о нажатии клавиши на клавиату-

ре.

Лабораторная работа № 4. Работа с файлами. Создание файла, манипуляция с файлом, поиск записи в файле и т.д.

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

Основная литература: 3[51-123], 5[348-353] Дополнительная литература: 11[31-100], 13[62-68,211-222]

Контрольные вопросы:

1.Какие API-функции необходимы при работе с файлами.

2.Какой набор функций обеспечивает перемещение указателя файла.

3.Каким образом выполняется чтение текста в буфер и вывод на экран.

4.Каким образом выполняется поиск заданного блока в файле и его вывод на экран.

5.По какому алгоритму производится чтение и запись в файл.

Лабораторная работа № 5. Процессы и потоки. Синхронизация и управление.

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

Основная литература: 3[200-234, 237-268, 271-307] , 5[75-137,197-233, 280-327]

Дополнительная литература: 11[211-265], 14[167-179, 199-220]

Контрольные вопросы:

1.Какие функции применяются при работе с процессами и потоками.

2.Какими параметрами характеризуются процесс и поток.

3.В чем принципиальное различие между процессом и потоком.

4.Как узнать код завершения потока.

5.Как измерить время работы процесса, потока.

6.Классы приоритетов потока и процесса.

Лабораторная работа № 6. Работа с директориями. Понятия об атрибутах записей в директории. Вывести текущий директорий.

Задание: Разработать программу для вывода текущего директория на -эк ран. Определить атрибут очередной записи(файл или директорий) и вывести соответствующую запись разным шрифтом: если запись это файл– вывод делать строчными буквами, если запись директорий – вывод делать прописными буквами.

Основная литература: 3[87-123]

76

Дополнительная литература: 14[62-89]

Контрольные вопросы:

1.Как определить атрибут записи?

2.Какой функцией надо воспользоваться для вывода директория.

3.Как определить текущий директорий.

4.Какие функции применяются для управления директориями.

Лабораторная работа № 7.Табличное преобразование символов из одного вида кодировки в другой вид.

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

Дополнительная литература: 11[4-69], 13[160-208, 312-318, 335-339], 23[32, 305-309]

Контрольные вопросы:

1.Какие таблицы кодирования Вы знаете?

2.Чем отличаются таблицы кодировки?

3.Каким образом осуществляется кодировка символов?

4.При помощи, каких команд можно реализовать простой способ кодирования символов?

Лабораторная работа № 8. Шифрование, расшифровывание информации. Задание: Написать программу шифрования, дешифрирования информации применяя различные алгоритмы: Виженера, Тритемия, ДифиХелмана, RSA и т.

д

Дополнительная литература: 11[4-69], 13[160-208, 312-318, 335-339], 13[32, 305-309]

Контрольные вопросы:

1.Какая защита применяется в ОСWindows.

2.Какая модель безопасности используется в ОСWindows.

3.Какие функции применяются для организации шифрования информа-

ции.

4.Каким образом производится анализ записей файла.

5.Как организовать опрос символов файлов для шифрования.

2.4 Планы занятий в рамках самостоятельной работы обучающихся под руководством преподавателя (СРОП)

Задание

Форма

про-

Методические рекоменда-

Рекомендуемая

 

 

ведения

 

ции

литература

 

 

 

 

 

 

 

 

1

2

 

3

 

4

1.

Символьные и строковые ти-

Опрос

 

Изучить типы данных

3осн.

[11-35],

пы данных для ANSI и Unicode

 

 

 

2осн. [116-123]

2.

Unicode- и ANSI-функции в

Опрос

 

Изучить ANSI-функции

3осн.

[11-35],

 

 

 

 

 

2осн. [116-123]

77

Windows

 

 

 

 

Windows

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3. Unicode- и ANSI-функции

в

Коллоквиум,

Изучить ANSIфункции

 

3осн.

[11-35],

библиотеке С, С++

 

 

Опрос

в С, С++

 

 

 

 

 

2осн. [116-123]

 

 

 

 

 

 

 

 

 

 

4.

Работа

администратора

 

Коллоквиумс,

Изучить

полномочия

ад-

 

3осн. [126-137]

пользовательскими

полномо-

Опрос

министратора

 

 

 

 

 

 

чиями

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5.

Объекты

ядра,

задания, во-

Коллоквиум,

Изучить

вопросы

вклю-

 

3осн.[37-68,144-

локна

 

 

 

Опрос

чения, завершения

про-

 

167,422-426]

 

 

 

 

 

 

цессов в задании, работу

 

 

 

 

 

 

 

 

 

с волокнами

 

 

 

 

 

 

 

 

 

 

 

 

 

6. Пулы потоков

 

 

Коллоквиум,

Исследовать

организа-

3осн.[397-422]

 

 

 

 

 

Опрос

цию пула потоков

 

 

 

 

 

 

 

 

 

 

 

 

7. Стек потока

 

 

Коллоквиум,

Исследовать стек потока

 

3осн. [523-536]

 

 

 

 

 

Опрос

 

 

 

 

 

 

 

 

8. Динамическая локальная па-

Коллоквиум,

Исследовать

динамиче-

 

3осн[.681-689]

мять потока

 

 

 

Опрос

скую локальную память

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

9.

Статическая локальная

-па

Коллоквиум,

Исследовать

 

 

 

 

3осн. [681-689]

 

статиче-

 

мять потока

 

 

 

Опрос

скую локальную память

 

 

 

 

 

 

 

 

 

 

10.

Эффективное

управление

Коллоквиум,

Изучить

способы

эффек-

1осн.[155-198]

памятью

 

 

 

Опрос

тивного использования и

3осн. [431-460,

 

 

 

 

 

 

управления памятью

 

 

601-612]

 

 

 

 

 

 

 

11.

Исследование

виртуальной

Коллоквиум,

Рассмотреть способы по-

3осн.[460-487]

памяти

 

 

 

Опрос

лучения

системной

-ин

 

 

 

 

 

 

 

 

формации, статуса

 

вир-

 

 

 

 

 

 

 

 

туальной памяти

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

12.

Использование

виртуальной

Коллоквиум,

Изучить

 

 

 

 

 

3осн.[487-523]

 

применение

 

памяти в приложениях

 

Опрос

виртуальной

памяти

в

 

 

 

 

 

 

 

приложениях

 

 

 

 

 

 

 

 

 

 

 

 

 

 

13.

Использование

проецируе-

Коллоквиум,

Изучить

принципы

про-

3осн. [536-598]

мых в память файлов

 

Опрос

ецирования файлов в па-

 

 

 

 

 

 

 

 

мять

 

 

 

 

 

 

 

 

 

 

 

14. Отладчики и дизассемблеры

Коллоквиум,

Исследовать способы ис-

2осн. [641-708,

 

 

 

 

 

опрос

следования программ

 

 

711-754]

 

 

 

 

 

 

15. Драйверы, разработка драй-

Коллоквиум,

Исследовать

структуру2осн.

[641-708,

веров

 

 

 

опрос

драйверов и методы раз-

711-754]

 

 

 

 

 

 

 

работки

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

78

2. 5 Планы занятий в рамках самостоятельной работы обучающихся (СРО)

Задание

Методические

Рекомендуемая

 

рекомендации

литература

1

2

3

 

1. Структуры программ для ОС

Изучить структуру программ

1осн. [17-50],

Windows

 

2осн.

[31-54,

 

 

551-559]

 

2. Организация и особенности

Изучить основы операционных сис-

1осн. [28-50, 510-

Win32 и Win64

тем и принципы организации

524],

 

 

 

14доп. [19-36]

3. Реестр ОС Windows Vista, Win-

Изучить структуру реестра

1осн. [111-122]

dows Seven

 

 

 

 

 

 

4. Файловая система

Изучить и провести анализ

1осн.[51-85]

 

 

 

5. Управление памятью и указате-

Изучить принципы и методы управ-

3осн[432-460]

ли.

ления памятью

 

 

 

 

 

6. Работа с памятью на низкомРассмотреть работу с памятью на

20доп[21-52]

уровне

низком уровне

 

 

 

 

 

7. DLL и адресное пространство

Изучить адресное пространство про-

3осн.[616-681]

процесса

цесса и использование DLL

 

 

 

 

 

8. Внедрение DIL и перехват API -

Изучить процесс внедрения DIL и ме-

3осн. [689-747]

вызовов

тоды перехвата API - вызовов

 

 

 

 

 

9. Структурная обработка исклю-

Исследовать исключения и их обра-

1осн. [26-153],

чений

ботку

3осн. [747-795],

 

 

14доп. [90-111]

10. Использование фильтров и об-

Изучить обработчики исключений и

1осн. [126-153],

работчиков исключений

фильтры

3осн. [747-795],

 

 

14доп. [90-111]

11. Переадресация вызовов функ-

Изучить методы переадресации и пе-

3осн. [634-681]

ций и перенаправление DLL

ренаправления

 

 

 

 

 

12. Модификация базовых адресов

Изучить способы модификации

3осн. [670-681]

модулей и связывание модулей

 

 

 

 

 

 

13. Интерфейс графических уст-

Исследовать способы обработки

2осн. [31-92],

ройств

 

11доп. [3-69],

 

 

16доп. [5-86]

14. Механизмы защиты ОС Win-

Изучить основные механизмы орга-

1осн. [483-509],

dows Vista, Windows Seven

низации защиты

14доп.[112-131]

 

 

 

15. Сокеты и сетевое программи-

Изучить сокеты и их применение при

1осн. [394-429]

рование

сетевом программировании

14доп[.313-340]

 

 

 

 

2.6 Тестовые задания для самоконтроля (30 вопроса)

&&&1. Главным элементом программы в среде Windows является: A) окно

79

B)точка

C)строка

D)символ

E)список

&&&2. Операционная система Windows использует модель памяти A) не линейную

B) линейную

C) каноническую D) виртуальную E) конвеерную

&&&3. Работу системных Win32 API обеспечивает ядро

A)win32k.sys

B)csrss.exe

C)ntoskrnl.exe

D)windowExA.sys

E)getMessage.exe

&&&4. В семействе процессоров IA-32 выбор метода обращения к памяти определяется

A) объемом памяти B) размером данных

C) состоянием регистров управления D) режимом работы процессора

E) типом выполняемой задачи

&&&5. В защищенном режиме сегмент определяется с помощью

A)флага состояния

B)регистра управления

C)состояния процессора

D)адреса

E)дискриптора

&&&6. Биты поля доступа (access field) дескриптора сегмента определяют A) режим работы процессора

B) способ использования сегмента C) приоритет

D) привилегии

E) ) состояния процессора

&&&7. Virtual memory manager обеспечивает

A) работоспособность процессора

80

B)работоспособность системы виртуальной памяти

C)работоспособность графического интерфейса

D)режим работы процессора

E)определение привилегий

&&& 8. Основным модулем выполнения в Win32 является

A)программа

B)процесс

C)приложение

D)окно

E)поток

&&&9. Консольное приложение

A) Notepad B) Calculator C) Wordpad D) Paint

E) cmd.exe

&&&10. Модулю, загружаемому в адресное пространство присваивается A) уникальный описатель экземпляра

B) адрес C) индекс

D) приоритет E) режим

&&&11. Процесс создается функцией

A)CreateProcess

B)TerminateProcess

C)GetModuleProcess

D)DebugProcess

E)ExitProcess

&&& 12. Классы приоритета влияют на

A) распределение процессорного времени между процессами и их потоками

B)распределение адресного пространства между потоками и процессами

C)распределение ресурсов между потоками и процессами

D) распределение виртуального пространства между потоками и процессами

E) распределение сообщений между потоками и процессами

81

&&&13. Процесс может завершиться, если один из потоков процесса вызывает функцию

A) DebugProcess B) ExitProcess

C) TerminateProcess D) GetModuleProcess E) CreateProcess

&&&14. Любой поток может завершить любой процесс с функцией

A)GetModuleProcess

B)ExitProcess

C)TerminateProcess

D)CreateProcess

E)DebugProcess

&&&15. Размер файла можно определить с помощью функции

A) WriteFile B) CreateFile C) DebugFile D) FindFirstFile E) ExitFile

&&&16. Установить размер файла можно с помощью функции

A) SetEndOfFile B) FindFirstFile C) WriteFile

D) CreateFile E) ReadFile

&&&17. Функция FindFirstFile возвращает

A)Дескриптор памяти

B)Дескриптор процесса

C)Дескриптор потока

D)Дескриптор файла

E)Дескриптор поиска

&&& 18. Функция закрытия дескриптора поиска

A)CloseHandle

B)FindFirstFile

C)SetEndOfFile

D)CreateFile

E)FindClose

82

&&&19. CreateMutex применяется для создания A) объекта-мьютекса

B) семафора C) таймера D) процесса E) потока

&&&20. Для организации монопольного доступа к файлу используется

A) SetEndOfFile B) LockFile

C) SetFilePointerEx D) UnlockFile

E) FindClose

&&&21. Доступ к реестру осуществляется

A)lockFile

B)unlockFile

C)registry keys

D)unlockFile

E)findClose

&&&22. Функция RegEnumValue используется для A) удаления раздела п

B) создания новых разделов

C) задания атрибутов безопасности

D) установки значения параметров в открытом разделе E) вывода значений параметров открытого раздела

&&&23. Операция выделения региона называется

A)heap manager

B)paging

C)dynamiclink

D)reserving

E)relative

&&& 24. Записать измененные данные в дисковый образ файла можно

A)CloseHandle

B)MapViewOfFileEx

C)FlushViewOfFile

D)GetModuleHandle

E)GetProcAddress

83

&&&25. Одностороннее символьно-ориентированное межпроцессное взаимодействие позволяет проводить

A) именованный канал B) клиент

C) анонимный канал D) протокол

E) сервер

&&&26. ASL это

A)набор элементов управления доступом

B)набор идентификаторов памяти

C)набор идентификаторов группы

D)список доступных каналов

E)список доступных адресов

&&&27. Размер собственного виртуального адресного пространства процесса составляет

A) 1Мбайт B) 4Гбайт C) 1 Кбайт D) 4Мбайт E) 64Кбайт

&&&28. Неявное связывание это

A)связывание во время выполнения

B)связывание во время загрузки

C)связывание во время выхода

D)связывание во время запуска приложения

E)связывание во время закрытия приложения

&&&29. Объекты, представляющие широковещательный механизм A) анонимные каналы

B) именованные каналы C) почтовые ячейки

D) серверы E) клиенты

&&&30. Совмещение возможности ввода-вывода с перекрытием и возможности независимых потоков обеспечивают

A) почтовые ячейки

B) порты завершения ввода-вывода C) именованные каналы

D) анонимные каналы

84

E) клиент

Правильные ответы

Номера

Правильный

Номера

Правильный

Номера

Правильный

вопросов

ответ

вопросов

ответ

вопросов

ответ

1

A

11

A

21

C

2

B

12

A

22

E

3

C

13

B

23

D

4

D

14

C

24

C

5

E

15

D

25

C

6

B

16

A

26

A

7

B

17

E

27

B

8

E

18

E

28

B

9

E

19

A

29

C

10

A

20

B

30

B

2.7 Перечень экзаменационных вопросов по пройденному курсу(85 вопросов)

1.Общие положения о программировании в Windows.

2.Функции API. Классификация функций API.

3.Архитектура Windows.

4.Адресация памяти. Режимы работы процессора.

5.Модели памяти. Таблицы дескрипторов.

6.Страничная организация памяти.

7.Сегментная организация памяти.

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

9.Преобразование линейного адреса в физический с учетом страничной организации.

10.Набор базовых функций интерфейсов программирования.

11.Процессы. Функция создания процесса, параметры.

12.Идентификация процессов. Параметры.

13.Ожидание завершения процесса.

14.Завершение процесса, способы. Функции завершения процесса.

15.Потоки. Функция создания потока, параметры.

16.Планирование потоков, приоритеты потоков, возобновление потоков.

17.Синхронизация потоков с использованием объектов ядра.

18.Синхронизация потоков в пользовательском режиме.

19.Задание. Получение статистической информации о задании.

20.Удаленные потоки.

21.Локальная память потока.

22.Приоритеты потоков и процессов.

23.Критические секции и защита данных.

24.Мьютексы, события и модель переменных состояния.

85

25.Файловая система, управление файлами

26.Объекты ядра и синхронизация потоков

27.Создание, открытие, запись, удаление файла.

28.Определение размеров файла, определение и изменение атрибутов

файла.

29.Установка указателя и конца файла.

30.Блокирование и разблокировка файла.

31.Управление файлами.

32.Управление каталогами.

33.Реестр. Управление разделами.

34.Реестр. Управление параметрами.

35.Атрибуты файлов и работа с каталогами.

36.Стратегии обработки файлов.

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

38.Разделы адресного пространства

39.Регионы в адресном пространстве.

40.Использование виртуальной памяти в приложениях.

41.Стек потока.

42.Стандартная куча процесса.

43.Функции управления кучами

44.Взаимодействие между процессами

45.Анонимные каналы.

46.Именованные каналы. Создание именованных каналов.

47.Функции состояния именованных каналов.

48.Почтовые ящики. Создание и открытие.

49.Обработка аппаратных исключений.

50.Обработка программных исключений.

51.Обработчики исключений.

52.Ошибки и исключения.

53.Исключения и их обработчики.

54.Функция UnhandledExceptionFilter, этапы обработки исключений.

55.Механизм векторной обработки исключений(vectored exception handling, VEH).

57.Учетные записи.

58.Идентификаторы безопасности.

59.Дескрипторы безопасности.

60.Списки управления доступом ACL.

61.Маркеры доступа.

62.Схема взаимодействия компонент системы безопасности.

63.Функция получения информации о пользователе.

64.Структура идентификатора безопасности.

65.Стандартные устройства ввода-вывода.

66.Функции консольного ввода-вывода.

86

67.Асинхронный ввод-вывод.

68.API функции для работы с реестром.

69.Объекты отображения в память.

70.API функции для работы с виртуальной памятью.

71.Ограничения, налагаемые на процессы в задании.

72.Создание событий управления консоли.

73.Приоритеты потоков и процессов.

74.Кучи, управление памятью кучи.

75.Последовательность действий при работе с кучей.

76.Динамические библиотеки. Явное и неявное связывание.

77.Стандартные устройства и консольный ввод-вывод.

78.Обработчики управления консоли.

79.Обзор элементов безопасности: дескриптор безопасности.

80.Управление списками ACL.

81.Чтение и изменение дескриптора безопасности.

82.Распределение памяти под идентификатор безопасности.

83.Получение статической информации о файле.

84.Создание идентификатора безопасности

85.Структура системы безопасности ОС Windows.

87

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