Автор работы: Пользователь скрыл имя, 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
Первая состоит в вопросе - если одна задача производит данные, а вторая их потребляет, то как задача-потребитель узнает, что готова очередная порция данных? Или, что еще интереснее, как она узнает, что очередная порция данных еще не готова? Типичный случай такого взаимодействия - асинхронное чтение с диска, когда программа дает дисковому драйверу запрос: «читай с такого-то сектора в такой-то блок памяти», и продолжает заниматься своими делами.
Вторая проблема - проблема критических секций. Например, одна программа вставляет данные в разделяемый двунаправленный список, а другая достает их оттуда. Попытка произвести в этот момент какую-то другую операцию изменения списка приведет к полному разрушению его структуры, а чтение или поиск закончатся аварией. Поэтому изменяющая программа должна каким-то образом блокировать доступ к списку на время изменения. Часто это делается теми же средствами, что и разделение ресурсов.
Большинство решений всех вышеперечисленных проблем сводится к созданию какого-то средства, сообщающего программе, что произошло то или иное внешнее или внутреннее событие. При этом программа может остановиться, ожидая заданного события.
Чтобы создать тот или иной объект синхронизации, производится вызов специальной функции WinAPI типа Create (напр. CreateMutex). Этот вызов возвращает дескриптор объекта (HANDLE), который может использоваться всеми потоками, принадлежащими данному процессу. Есть возможность получить доступ к объекту синхронизации из другого процесса - либо унаследовав дескриптор этого объекта, либо, что предпочтительнее, воспользовавшись вызовом функции открытия объекта (Open...). После этого вызова процесс получит дескриптор, который в дальнейшем можно использовать для работы с объектом. Объекту, если только он не предназначен для использования внутри одного процесса, обязательно присваивается имя. Имена всех объектов должны быть различны (даже если они разного типа). Нельзя, например, создать событие и семафор с одним и тем же именем.
По имеющемуся дескриптору объекта можно определить его текущее состояние. Это делается с помощью т.н. ожидающих функций. Чаще всего используется функция WaitForSingleObject (см. Приложение). Эта функция принимает два параметра, первый из которых - дескриптор объекта, второй - время ожидания в мсек. Функция возвращает WAIT_OBJECT_0, если объект находится в сигнальном состоянии, WAIT_TIMEOUT - если истекло время ожидания, и WAIT_ABANDONED, если объект-взаимоисключение не был освобожден до того, как владеющий им поток завершился. Если время ожидания указано равным нулю, функция возвращает результат немедленно, в противном случае она ждет в течение указанного промежутка времени. В случае, если состояние объекта станет сигнальным до истечения этого времени, функция вернет WAIT_OBJECT_0, в противном случае функция вернет WAIT_TIMEOUT. Если в качестве времени указана символическая константа INFINITE, то функция будет ждать неограниченно долго, пока состояние объекта не станет сигнальным. Если необходимо узнавать о состоянии сразу нескольких объектов, следует воспользоваться функцией WaitForMultipleObjects (см. Приложение). Чтобы закончить работу с объектом и освободить дескриптор вызывается функция CloseHandle. Очень важен тот факт, что обращение к ожидающей функции блокирует текущий поток, т.е. пока поток находится в состоянии ожидания, ему не выделяется процессорного времени.
Существуют следующие методы синхронизации:
1 прерывания и сигналы;
2 семафоры;
3 блокировка участков файлов;
4 гармонически взаимодействующие последовательные процессы.
Прерывания, вызванные внутренними событиями, часто называют исключениями (exceptions). Исключения возникают при делении на ноль, неопределенном коде команды, ошибках обращения к памяти и т.д.
Реализации прерываний и исключений у разных процессоров немного отличаются.
Легко видеть, что прерывания и сигналы могут служить для оповещения программы о событии, но не решают ни одной из проблем, а напротив, создают их. Действительно, подпрограмму обработки прерывания во многих отношениях можно рассматривать как параллельно исполняемый процесс.
К счастью, аппаратные реализации позволяют запрещать все или некоторые прерывания, и мы можем решить таким образом проблему критической секции. Однако, такое решение часто оказывается неудовлетворительным или просто нереализуемым. Например, в системах реального времени нельзя запрещать прерывания надолго. Поэтому программа обработчика прерывания в плохо спроектированной ОС, в ДОС или на "голой" машине часто вынуждена заниматься тонкой игрой аппаратными уровнями прерывания. Такая игра доставляет много удовольствия молодым хакерам, но может приводить к тонким и очень труднообнаружимым ошибкам.
Эти ошибки состоят в неправильном определении границ критических секций. Они очень плохо воспроизводятся при тестировании, потому что для срабатывания ошибки необходимо возникновение прерываний в строго определенной последовательности и в заданные относительные моменты времени. Поймать такую ошибку под интерактивным отладчиком практически невозможно.
Кроме того, программу, работающую совместно с процедурами обработки прерываний, нельзя представить в виде детерминированного конечного автомата. Это усложняет анализ алгоритмов и доставило в свое время много волнений теоретикам программирования.
С практической точки зрения, наиболее серьезным недостатком прерываний является то, что прерывания предоставляют только механизм сообщения программе о том, что какое-то событие произошло.
Семафор Дийкстры представляет
собой целочисленную
Закрытие семафора соответствует захвату ресурса, доступ к которому контролируется этим семафором. Процесс, закрывший семафор, захватывает ресурс. Если ресурс захвачен, остальные процессы вынуждены ждать его освобождения. Закончив работу с ресурсом, процесс увеличивает значение семафора на единицу, открывая его. При этом первый из стоявших в очереди процессов активизируется, вычитает из значения семафора единицу, и снова закрывает семафор. Если же очередь была пуста, то ничего не происходит, просто семафор остается открытым. Тогда первый процесс, подошедший к семафору, успешно пройдет через него. Это действительно похоже на работу железнодорожного семафора, контролирующего движение поездов по одноколейной ветке.
Наиболее простым случаем семафора является двоичный семафор. Начальное значение флаговой переменной такого семафора равно 1, и вообще она может принимать только значения 1 и 0. Двоичный семафор соответствует случаю, когда с разделяемым ресурсом в каждый момент времени может работать только одна программа.
Семафоры общего вида
могут принимать любые
Можно показать, что любые проблемы взаимодействия и синхронизации процессов могут быть решены при помощи семафоров. На практике трудности иногда оказываются не то, чтобы слишком большими, но нежелательными.
Существует два типа блокировок: на чтение и на запись. Блокировка на чтение разрешает другим процессам читать из заблокированного участка и даже ставить туда такую же блокировку, но запрещает писать в этот участок и, тем более, блокировать его на запись. Этим достигается уверенность в том, что структуры данных, считываемые из захваченного участка, никем не модифицируются, поэтому гарантирована их целостность и непротиворечивость.
В свою очередь, блокировка на запись запрещает всем, кроме блокирующего процесса, любой доступ к заблокированному участку файла. Это означает, что данный участок файла сейчас будет модифицироваться, и целостность данных в нем не гарантирована.
При работе с разделяемыми структурами данных в ОЗУ было бы удобно иметь аналогичные средства, но их реализация ведет к большим накладным расходам, даже на системах с виртуальной памятью, поэтому ни одна из известных авторам систем таких средств не предоставляет.
Разделяемые структуры данных являются предметом ненависти теоретиков и источником серьезных ошибок при разработке программ. Легко показать, что критические секции может иметь только программа, работающая с разделяемыми структурами данных. И этими критическими секциями как раз и являются места, где программа модифицирует такие структуры или просто обращается к ним. Синхронизация доступа к разделяемым структурам часто приводит к усложнению программы, а стремление сократить участки исключительного доступа - к ошибкам.
Желание устранить эти проблемы привело в свое время Дийкстру к концепции, известной как гармонически взаимодействующие последовательные процессы. Эта концепция состоит в следующем:
Концепция гармонически
взаимодействующих процессов
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:
DWORD WaitForSingleObject(
HANDLE hObject,
DWORD dwTimeout);
10 функция WaitForMultipleObjects:
DWORD WaitForMultipleObjects(
DWORD cObjects,
CONST HANDLE *lphObjects,
BOOL fWaitAll,
DWORD dwTimeout);
В данной работе была рассмотрена организация синхронизации в Windows. Без синхронизации наши машины долго бы еще не смогли выполнять сложные многопроцессорные задачи. А это, в свою очередь, сильно отразилось бы на трудовой производительности и экономности времени.
1. http://www.sofmos.com/lyosha/
2. http://www.rsdn.ru/article/
3. http://www.codenet.ru/progr/
4. http://www.cyberguru.ru/cpp-
5.http://cbuilder.inf.ua/
6. http://www.frolov-lib.ru/
7. http://unixoid.spb.ru/OS/
Информация о работе Cинхронизация Windows. Процессы, потоки и методы синхронизации