Добавил:
Developerrnrn Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОС Нижний.pdf
Скачиваний:
34
Добавлен:
25.03.2023
Размер:
2.75 Mб
Скачать

Лабораторный практикум по курсу "Операционные системы"

виртуальной памяти некоторого процесса. Флаги IPC_CREAT и IPC_EXCL аналогичны рассмотренным выше.

Подключение сегмента к виртуальной памяти выполняется путем обращения к системному вызову shmat():

void *virtaddr = shmat(int shmid, void *daddr, int flags).

Параметр shmid - это ранее полученный идентификатор сегмента, а daddr - желаемый процессом виртуальный адрес, который должен соответствовать началу сегмента в виртуальной памяти. Значением системного вызова является фактический виртуальный адрес начала сегмента. Если значением daddr является NULL, ядро выбирает наиболее удобный виртуальный адрес начала сегмента. Флаги системного вызова shmat() приведены ниже в таблице.

Таблица Флаги системного вызова shmat()

SHM_RDONLY

ядро подключает участок памяти только для чтения;

 

 

SHM_RND

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

 

daddr.

 

 

Для отключения сегмента от виртуальной памяти используется системный вызов shmdt(): int shmdt(*daddr);

где daddr - это виртуальный адрес начала сегмента в виртуальной памяти, ранее полученный от системного вызова shmat().

Системный вызов shmctl:

int shmctl (int shmid, int command, struct shmid_ds *shm_stat);

по синтаксису и назначению системный вызов полностью аналогичен msgctl().

Механизмы межпроцессного взаимодействия ОС Windows

Ниже кратко описаны некоторые системные вызовы, которые могут потребоваться при выполнении лабораторной работы в ОС Windows.

Wait-функции

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

WaitForSingleObject:

DWORD WaitForSingleObject( HANDLE hObject, DWORD dwMilliseconds);

Когда поток вызывает эту функцию, первый параметр, hObject, идентифицирует объект ядра, поддерживающий состояния «свободен-занят» Второй параметр, dwMilliseconds, указывает, сколько времени (в миллисекундах) поток готов ждать освобождения объекта.

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

WaitForSingleObject(hProcess, INFINITE);

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

138 Учебно-исследовательская лаборатория «Информационные технологии»

Лабораторный практикум по курсу "Операционные системы"

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

Вот пример, иллюстрирующий, как вызывать WaitForSingleObject co значением таймаута, отличным от INFINITE

DWORD dw = WaitForSlngleObject(hProcess, 5000); switch (dw)

{

case WAIT_OBJECT_0:

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

case WAIT_TIMEOUT:

// процесс не завершился в течение 5000 мс break;

case WAIT_FAILED:

// неправильный вызов функции (неверный описатель?) break;

}

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

DWORD WaitForMultipleObjects( DWOHD dwCount,

CONST HANDLE* phObjects, BOOL fWaitAll,

DWORD dwMilliseconds);

Параметр dwCount определяет количество интересующих Вас объектов ядра Его значение должно быть в пределах от 1 до MAXIMUM_WAIT_OBJECTS (в заголовочных файлах Windows оно определено как 64). Параметр phObject — это указатель на массив описателей объектов ядра.

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

Параметр dwMilliseconds идентичен одноименному параметру функции WaitFor SingleObject Если Вы указываете конкретное время ожидания, то по его истечении функция в любом случае возвращает управление. И опять же, в этом параметре обычно передают INFINITE (будьте внимательны при написании кода, чтобы не создать ситуацию взаимной блокировки).

Возвращаемое значение функции WaitForMultipleObjects сообщает, почему возобновилось выполнение вызвавшего ее потока Значения WAIT_FAILED и WAIT_TIMEOUT никаких пояснений не требуют. Если Вы передали TRUE в параметре fWaitAll и все объекты перешли в свободное состояние, функция возвращает значение WAIT_OB JECT_0. Если fWaitAll

Учебно-исследовательская лаборатория «Информационные технологии» 139

Лабораторный практикум по курсу "Операционные системы"

приравнен FALSE, она возвращает управление, как только ос вобождается любой из объектов. Вы, по-видимому, захотите выяснить, какой именно объект освободился В этом случае возвращается значение от WAIT_OBJECT_0 до WAIT_OBJECT_0 + dwCount - 1.

Иначе говоря, если возвращаемое значение не равно WAIT_TIMEOUT или WAIT_FAILED, вычтите из него значение WAlT_OBJECT_0, и Вы получите индекс в массиве описателей, на который указывает второй параметр фун кции WaitForMultipleObjects.

События

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

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

Первые позволяют возобновлять выполнение сразу нескольких ждущих потоков, вторые — только одного.

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

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

HANDLE CreateEvent( PSECURITY_ATTRIBUTES psa, BOOL fManualReset,

BOOL fInitialState, PCTSTR pszName);

Параметр fManualReset (булева переменная) сообщает системе, хотите Вы создать событие со сбросом вручную (TRUE) или с автосбросом (FALSE). Параметру fInitialState определяет начальное состояние события — свободное (TRUE) или занятое (FALSE). После того как система создает объект событие, CreateEvent возвращает описатель события, специфичный для конкретного процесса. Потоки из других процессов могут получить доступ к этому объекту: 1) вызовом CreateEvent с тем же параметром pszName;, 2) наследованием описателя; 3) применением функции DuplicateHandle;, и 4) вызовом OpenEvent c передачей в параметре pszName имени, совпадающего с указанным в аналогичном параметре функции CreateEvent. Вот что представляет собой функция OpenEvent.

HANDLE OpenEvent( DWORD fdwAccess, BOOL fInhent, PCTSTR pszName);

Чтобы перевести объект в свободное состояние, Вы вызываете:

BOOL SetEvenT(HANDLE hEvenеt);

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

BOOL ResetEvent(HANDLE hEvent);

140 Учебно-исследовательская лаборатория «Информационные технологии»

Лабораторный практикум по курсу "Операционные системы"

Ожидаемые таймеры

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

HANDLE CreateWaitableTimer(

PSECURITY_ATTRIBUTES psa,

 

BOOL fManualReset,

 

PCTSTR pszName);

HANDLE OpenWaitableTirrer(

DWORD dwDesiredAccess,

 

BOOL bInheritHandle,

 

PCTSTR pszName);

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

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

SetWaitableTimer.

BOOL SetWaitableTimer( HANDLE hTimer,

const LARGE_INTEGER *pDueTime, LONG lPeriod,

PTIMERAPCROUTINE pfnCompletionRoutine, PVOID pvArgToCotnpletionRoutine,

BOOI fResume);

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

Другая функция -

BOOL CancelWaitableTimer(HANDLE hTimer);

Эта очень простая функция принимает описатель таймера и отменяет его (таймер), после чего тот уже никогда не сработает, — если только Вы не переустановите его повторным вызовом SetWaitableTimer. Если Вам понадобится перенастроить таймер, то вызывать CancelWattableTimer перед повторным обращением к SetWaitableTimer не требуется; каждый вызов SetWaitableTimer автоматически отменяет предыдущие настройки перед установкой новых.

Семафоры

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

Учебно-исследовательская лаборатория «Информационные технологии» 141

Соседние файлы в предмете Современные операционные системы