Cинхронизация Windows. Процессы, потоки и методы синхронизации

Автор работы: Пользователь скрыл имя, 03 Сентября 2013 в 08:20, курсовая работа

Описание работы

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

Содержание работы

1 Введение ………………………………………………………..…………….…5
2 Процессы и потоки……………………………………………………………...6
3 Синхронизация потоков………………….…………………………………...8
3.1 необходимость синхрониза-ции……………………………………….8
3.2 механизм синхронизации и ее объекты……………………..……...8
3.3 проблемы синхронизации……………………………………………10
3.4 работа с объектами синхрониза-ции………………………………..11
4 Методы синхронизации……………………………….……........................12
4.1 методы прерываний и сигна-лов……..………………………….….12
4.2 метод семафоров ..…………………………………………………..13
4.3 метод блокировки …………………………………………………...14
4.4 метод гармонически взаимодействующих последовательных
процессов…………………………………………….…………………………..14
5 Приложение…………………………………………………………………….16
6 Заключение……………………………………………………………………..18
7 Библиографический список …………………………………………………..19

Файлы: 1 файл

Синхронизация Windows. Процессы, потоки и методы синхронизации.doc

— 122.00 Кб (Скачать файл)

3.3 проблемы синхронизации

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

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

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

3.4 работа с объектами синхронизации

Чтобы создать тот  или иной объект синхронизации, производится вызов специальной функции WinAPI типа Create (напр. CreateMutex). Этот вызов возвращает дескриптор объекта (HANDLE), который может использоваться всеми потоками, принадлежащими данному процессу. Есть возможность получить доступ к объекту синхронизации из другого процесса - либо унаследовав дескриптор этого объекта, либо, что предпочтительнее, воспользовавшись вызовом функции открытия объекта (Open...). После этого вызова процесс получит дескриптор, который в дальнейшем можно использовать для работы с объектом. Объекту, если только он не предназначен для использования внутри одного процесса, обязательно присваивается имя. Имена всех объектов должны быть различны (даже если они разного типа). Нельзя, например, создать событие и семафор с одним и тем же именем.

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

4 методы Синхронизации

Существуют следующие  методы синхронизации:

1 прерывания и сигналы;

2 семафоры;

3 блокировка участков  файлов;

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

4.1 метод прерываний и сигналов

Прерывания, вызванные внутренними событиями, часто называют исключениями (exceptions). Исключения возникают при делении на ноль, неопределенном коде команды, ошибках обращения к памяти и т.д.

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

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

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

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

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

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

4.2 метод семафоров

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

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

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

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

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

4.3 метод блокировки

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

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

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

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

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

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

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

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

5 приложение

1 функция GetThreadContext:

BOOL GetThreadContext( 

 HANDLE hThread, 

 LPCONTEXT lpContext

);

 

2 функция CreateMutex:

HANDLE CreateMutex 

 LPSECURITY_ATTRIBUTES lpMutexAttributes,  
 BOOL bInitialOwner,    
 LPCTSTR lpName     
);

 

3 функция EnterCriticalSection:

VOID EnterCriticalSection

(

LPCRITICAL_SECTION lpCriticalSection

 

);

 

4 функция EnterCriticalSection:

VOID LeaveCriticalSection

(

LPCRITICAL_SECTION lpCriticalSection

 

);

 

5 функция TryEnterCriticalSection:

BOOL TryEnterCriticalSection(

  LPCRITICAL_SECTION lpCriticalSection 

);

 

6 функция ResetEvent:

BOOL ResetEvent 

 HANDLE hEvent   
);

 

7 функция CreateEvent:

HANDLE CreateEvent 

 LPSECURITY_ATTRIBUTES lpEventAttributes, 
 BOOL bManualReset, 
 BOOL bInitialState, 
 LPCTSTR lpName 
);

 

8 функция SetEvent:

BOOL SetEvent 

 HANDLE hEvent 
);

 

9 функция PulseEvent:

BOOL PulseEvent(HANDLE hEvent);

DWORD WaitForSingleObject(

  HANDLE hObject,

  DWORD  dwTimeout);

 

10 функция WaitForMultipleObjects:

DWORD WaitForMultipleObjects(

  DWORD cObjects, 

  CONST HANDLE *lphObjects,

  BOOL  fWaitAll,

  DWORD dwTimeout); 

 

Заключение

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

 

7 Библиографический список

1. http://www.sofmos.com/lyosha/Articles/multithreading1.html

2. http://www.rsdn.ru/article/baseserv/mt.xml#ESB

3. http://www.codenet.ru/progr/cpp/process-threads-sync.php

4. http://www.cyberguru.ru/cpp-sources/win32/funktsii-createevent-setevent-resetevent.html

5.http://cbuilder.inf.ua/index.php?option=com_content&task=view&id=102&Itemid=2

6. http://www.frolov-lib.ru/books/bsp/v26/ch4_1.htm

7. http://unixoid.spb.ru/OS/node4.html

 


Информация о работе Cинхронизация Windows. Процессы, потоки и методы синхронизации