Операционные системы

Автор работы: Пользователь скрыл имя, 27 Августа 2013 в 21:46, контрольная работа

Краткое описание

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

Содержание

1. Организация файловой системы, назначение Master Boot Record и Boot Record.
2. Синхронизация процессов и потоков.
3. 3. Кэширование информации, условия установки кэш памяти, виды кэш памяти, влияние объёма кэш памяти на производительность ОС.
4. Выводы.
Список литературы.

Прикрепленные файлы: 1 файл

Операционные системы.doc

— 320.50 Кб (Скачать документ)

По имеющемуся дескриптору объекта можно определить его текущее состояние. Это делается с помощью так называемых ожидающих функций. Чаще всего используется функция WaitForSingleObject. Эта функция принимает два параметра, первый из которых - дескриптор объекта, второй - время ожидания в мсек. Функция возвращает WAIT_OBJECT_0, если объект находится в сигнальном состоянии, WAIT_TIMEOUT - если истекло время ожидания, и WAIT_ABANDONED, если объект-взаимоисключение не был освобожден до того, как владеющая им нить завершилась. Если время ожидания указано равным нулю, функция возвращает результат немедленно, в противном случае она ждет в течение указанного промежутка времени. В случае если состояние объекта станет сигнальным до истечения этого времени, функция вернет WAIT_OBJECT_0, в противном случае функция вернет WAIT_TIMEOUT. Если в качестве времени указана символическая константа INFINITE, то функция будет ждать неограниченно долго, пока состояние объекта не станет сигнальным.

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

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

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

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

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

Пример 6. Синхронизация  нитей с помощью критических  секций.

#include <windows.h>

#include <stdio.h>

CRITICAL_SECTION cs;

int a[5];

HANDLE hThr;

unsigned long uThrID;

void Thread( void* pParams )

{

int i, num = 0;

while (1)

{EnterCriticalSection( &cs );

for (i=0; i<5; i++) a[i] = num;

num++;LeaveCriticalSection( &cs );}

}int main( void )

{

InitializeCriticalSection( &cs );

hThr=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Thread,NULL,0,&uThrID);

while(1)

{

EnterCriticalSection( &cs );

printf("%d %d %d %d %d\n", a[0], a[1], a[2], a[3], a[4]);

LeaveCriticalSection( &cs );

}

return 0;

}

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

Объекты-взаимоисключения (мьютексы, mutex - от MUTual EXclusion) позволяют координировать взаимное исключение доступа к разделяемому ресурсу. Сигнальное состояние объекта (т.е. состояние "установлен") соответствует моменту времени, когда объект не принадлежит ни одной нити и его можно "захватить". И наоборот, состояние "сброшен" (не сигнальное) соответствует моменту, когда какая-либо нить уже владеет этим объектом. Доступ к объекту разрешается, когда нить, владеющая объектом, освободит его.

Две (или более) нити могут создать  мьютекс с одним и тем же именем, вызвав функцию CreateMutex. Первая нить действительно создает мьютекс, а следующие - получают дескриптор уже существующего объекта. Это дает возможность нескольким нитям получить дескриптор одного и того же мьютекса, освобождая программиста от необходимости заботиться о том, кто в действительности создает мьютекс. Если используется такой подход, желательно установить флаг bInitialOwner в FALSE, иначе возникнут определенные трудности при определении действительного создателя мьютекса.

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

  • Дочерний процесс, созданный при помощи функции CreateProcess может наследовать дескриптор мьютекса в случае, если при создании мьютекса функцией CreateMutex был указан параметр lpMutexAttributes.
  • Нить может получить дубликат существующего мьютекса с помощью функции DuplicateHandle.
  • Нить может указать имя существующего мьютекса при вызове функций OpenMutex или CreateMutex.

Для того чтобы объявить взаимоисключение принадлежащим текущей нити, надо вызвать одну из ожидающих функций. Нить, которой принадлежит объект, может его "захватывать" повторно сколько угодно раз (это не приведет к самоблокировке), но столько же раз она должна будет его освобождать с помощью функции ReleaseMutex.

Для синхронизации нитей одного процесса более эффективно использование критических секций.

Пример 7. Синхронизация нитей с  помощью мьютексов.

#include <windows.h>

#include <stdio.h>

HANDLE hMutex;

int a[5];

HANDLE hThr;

unsigned long uThrID;

void Thread( void* pParams )

{

int i, num = 0;

while (1)

{

WaitForSingleObject( hMutex, INFINITE );

for (i=0; i<5; i++) a[i] = num;

num++;

ReleaseMutex( hMutex );

}

}

int main( void )

{

hMutex=CreateMutex( NULL, FALSE, NULL );

hThr=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Thread,NULL,0,&uThrID);

while(1)

{

WaitForSingleObject( hMutex, INFINITE );

printf("%d %d %d %d %d\n", a[0], a[1], a[2], a[3], a[4]);

ReleaseMutex( hMutex );

}

return 0;

}

События

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

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

Пример 8. Синхронизация нитей с  помощью событий.

#include <windows.h>

#include <stdio.h>

HANDLE hEvent1, hEvent2;

int a[5];

HANDLE hThr;

unsigned long uThrID;

void Thread( void* pParams )

{

int i, num = 0;

while (1)

{

WaitForSingleObject( hEvent2, INFINITE );

for (i=0; i<5; i++) a[i] = num;

num++;

SetEvent( hEvent1 );}

}

int main( void )

{

hEvent1=CreateEvent( NULL, FALSE, TRUE, NULL );

hEvent2=CreateEvent( NULL, FALSE, FALSE, NULL );

hThr=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Thread,NULL,0,&uThrID);

while(1)

{

WaitForSingleObject( hEvent1, INFINITE );

printf("%d %d %d %d %d\n", a[0], a[1], a[2], a[3], a[4]);

SetEvent( hEvent2 );

}

return 0;

}

Семафоры

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

Функция CreateSemaphore создает объект-семафор с указанием и максимально возможного начального его значения, OpenSemaphore – возвращает дескриптор существующего семафора, захват семафора производится с помощью ожидающих функций, при этом значение семафора уменьшается на единицу, ReleaseSemaphore - освобождение семафора с увеличением значения семафора на указанное в параметре число.

Пример 9. Синхронизация нитей с  помощью семафоров.

#include <windows.h>

#include <stdio.h>

HANDLE hSem;

int a[5];

HANDLE hThr;

unsigned long uThrID;

void Thread( void* pParams )

{

int i, num = 0;

while (1)

{

WaitForSingleObject( hSem, INFINITE );

for (i=0; i<5; i++) a[i] = num;

num++;

ReleaseSemaphore( hSem, 1, NULL );

}

}

int main( void )

{

hSem=CreateSemaphore( NULL, 1, 1, "MySemaphore1" );

hThr=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Thread,NULL,0,&uThrID);

while(1)

{

WaitForSingleObject( hSem, INFINITE );

printf("%d %d %d %d %d\n", a[0], a[1], a[2], a[3], a[4]);

ReleaseSemaphore( hSem, 1, NULL );

}

return 0;

}

Защищенный доступ к переменным

Существует ряд функций, позволяющих  работать с глобальными переменными  из всех нитей, не заботясь о синхронизации, т.к. эти функции сами за ней следят – их выполнение атомарно. Это функции InterlockedIncrement, InterlockedDecrement, InterlockedExchange, InterlockedExchangeAdd и InterlockedCompareExchange. Например, функция InterlockedIncrement атомарно увеличивает значение 32-битной переменной на единицу, что удобно использовать для различных счетчиков.

Для получения полной информации о  назначении, использовании и синтаксисе всех функций WIN32 API необходимо воспользоваться  системой помощи MS SDK, входящей в состав сред программирования Borland Delphi или CBuilder, а также MSDN, поставляемым в составе системы программирования Visual C.

 

    1. Выводы

 

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

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

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

Таким образом:

    • в операционных системах, в которых существуют как процессы, так и потоки, процесс рассматривается операционной системой как заявка на потребление всех видов ресурсов, кроме одного — процессорного времени. Процессорное время распределяется ОС между другими единицами работы — потоками, представляющими собой последовательности команд;
    • потоки возникли в операционных системах как средство распараллеливания вычислений, облегчающее работу программиста. В ОС, не поддерживающей потоков, процесс всегда состоит из одного потока, а программисту приходится самостоятельно решать задачу синхронизации нескольких параллельных ветвей программы;
    • для синхронизации процессов и потоков, решающих общие задачи и совместно использующих ресурсы, в операционных системах существуют специальные средства: взаимоисключения (mutex); критические секции (critical section); события (event); семафоры (semaphore). Отсутствие синхронизации может приводить к таким нежелательным последствиям, как гонки и тупики.

Информация о работе Операционные системы