Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
3_СПОС_курсач_2009.doc
Скачиваний:
2
Добавлен:
09.11.2018
Размер:
208.9 Кб
Скачать

Возвращаемые значения

Если функция завершается успешно, возвращаемое значение - открытый дескриптор заданного файла. Если заданный файл существовал до вызова функции, а параметр dwCreationDisposition установлен в CREATE_ALWAYS или OPEN_ALWAYS, вызов GetLastError возвращает значение ERROR_ALREADY_EXISTS (даже при том, что функция завершилась успешно). Если файл не существовал перед вызовом функции, функция GetLastError возвращает нуль.

Далее, если открытие файла прошло без ошибок – создаем два потока:

if (_beginthread(thread2,1024,NULL)==-1)//Запуск второго потока чтения

cout <<rus("\nОшибка запуска 2 потока\n")<< endl;

else threadsWork++;

if (_beginthread(thread1,1024,NULL)==-1)//Запуск первого потока чтения

cout <<rus("\nОшибка запуска 1 потока\n")<< endl;

else threadsWork++;

Первым параметром в функцию _beginthread передается название запускаемого потока, вторым – размер стека, а третим – список параментров, в нашем случае NULL. Если при запуске потока произошла ошибка – выдаем сообщение, иначе добывляем один поток в список работающих.

char inBuffer[N+1]="\0"; буфер, в который будет помещен результат чтения по окончанию даного действия, где N – количество читаемых байт данных. Во избежании попадания в буфер «мусора» инициализируем его символом конца строки;

DWORD nBytesToRead=N - количество читаемых байт данных;

Прототип функции CreateEvent, служащей для создания события:

HANDLE CreateEvent

(

LPSECURITY_ATTRIBUTES lpEventAttributes,// атрибут защиты

BOOL bManualReset, // тип сброса TRUE - ручной

BOOL bInitialState, // начальное состояние TRUE - сигнальное

LPCTSTR lpName // имя обьекта

);

Эта функция возвращает дескриптор события, который мы присваиваем hEvent1.

Следующим шагом инициализируем структуру следующими значениями:

gOverLapped.Offset = 0;

gOverLapped.OffsetHigh = 0;

gOverLapped.hEvent = hEvent2;

чем и указываем, что мы должны читать с начала.

Теперь у нас все готово до вызова ReadFile:

ReadFile(hFile,&inBuffer,nBytesToRead,&nBytesRead,&gOverLapped);

ReadFile и WriteFile возвращают ненулевые значения, если запрошенный ввод-вывод выполнился синхронно, если же асинхронно или возникает ошибка — возвращают FALSE. В последнем случае, чтобы определить, что именно произошло, вызовите GetLastError. Если она возвращает ERROR_IO_PENDING, значит, запрос ввода-вывода успешно помещен в память и будет завершен позднее.

Если GetLastError возвращает отличное от ERROR_IO_PENDING значение, запрос не поставлен в очередь драйвера устройства. Вот самые распространенные коды ошибок, возвращаемые GetLastError, когда запрос ввода-вывода не может быть поставлен в очередь драйвера устройства;

-ERRORINVALIDUSERBUFFER или ERROR NOTENOUGHMEMORY

Каждый драйвер устройства поддерживает расположенный в неперемещаемом пуле список фиксированной длины, в котором содержатся ожидающиевыполнения запросы. Если этот список заполнен, система не может поставить в очередь ваш запрос и ReadFile или WriteFile возвращают FALSE, а функция GetLastError возвращает один из этих двух кодов ошибки (в зависимости от драйвера).

-ERROR_NOT_ENOUGH_QUOTA Некоторые устройства требуют, чтобы ваш буфер данных находился на закрепленной странице, чтобы данные не могли откачиваться из ОЗУ при ожидании ввода-вывода. Это требование всегда имеет место при установленно.м флаге FILE_FLAG_NO_BUFFERING. Но система ограничивает объем закрепленной памяти, выделяемый одному процессу. При невозможности разместить ваш буфер в неперемещаемой памяти ReadFile и WriteFile возвращают FALSE, а GetLastError — ERROR_NOT_ENOUGH_QUOTA. Увеличить квоту для процесса позволяет функция SetProcessWorkingSetSize.

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

CloseHandle

Функция CloseHandle закрывает открытый дескриптор объекта.

BOOL CloseHandle(

HANDLE hObject

);

Параметры

hObject

Дескриптор открытого объекта. Этим параметром может быть псевдо дескриптор или INVALID_HANDLE_VALUE(недействительный).

Возвращаемые значения

Если функции успешна, то возвращаемое значение не равно нулю.

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

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

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

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

WaitForSingleObject

Функция WaitForSingleObject возвращается, когда указанный объект находится в сигнальном состоянии или если время ожидания истекло.

DWORD WaitForSingleObject(

HANDLE hHandle,

DWORD dwMilliseconds

);

Параметры

hHandle

Дескриптор объекта.

Если дескриптор закрыт, когда ожидание этого объекта еще не закончено, то поведение функции не определено.

Дескриптор должен иметь право доступа SYNCHRONIZE. Узнать больше см. Standard Access Rights.

dwMilliseconds

Интервал ожидания в миллисекундах. Функция возвращается, если время истекло, даже если объект находится в несигнальном состоянии. Если параметр dwMilliseconds равен нулю, функция проверяет состояние объекта и немедленно возвращается. Если параметр dwMilliseconds равен INFINITE, то интервал ожидания функции не истечет никогда.

Возвращаемые значения

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

Возвращаемое значение/код

Описание

WAIT_ABANDONED 0x00000080L

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

WAIT_OBJECT_0 0x00000000L

Указанный объект находится в сигнальном состоянии.

WAIT_TIMEOUT 0x00000102L

Время ожидания истекло, и объект находится в несигнальном состоянии.

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

Замечания

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

Тестовые испытания

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

Заключение

В связи с тем, что в настоящее время широкое распространение получили многозадачные системы актуальной становится проблема синхронизации. При асинхронном чтении из файла самый простой способ синхронизации заключается в том, что задача, вызывающая функции ReadFile или WriteFile в асинхронном режиме, записывает в поле hEvent структуры OVERLAPPED значение NULL. После вызова указанных выше функций, когда задаче нужно дождаться завершения выполнения асинхронной операции, она вызывает функцию WaitForSingleObject, передавая ей в качестве первого параметра идентификатор файла. Другой способ предполагает создание отдельного объекта-события, идентификатор которого записывается в поле hEvent структуры OVERLAPPED при инициализации последней. В этом случае в качестве первого параметра функции WaitForSingleObject следует передать идентификатор этого объекта-события. Как только файловая операция будет завершена, объект-событие перейдет в отмеченное сосотояние.

В данной работе был выполнен обзор функций API для работы с событиями (events) ОС семейства Windows, разработана и написанана программа, для множественного асинхронного чтения данных из файла с использованием дескриптора и событиймеханизмов мьютексов WinApi, а также предложена программная реализация задачи читателей-писателей с их использованием с приоритетом по записи. Был проведен аналитический обзор литературы по данной тематике, что дало возможность разработать ряд алгоритмов и выбрать из них, на мой взгляд, наиболее устойчивое и быстродействующее решение, представленное в данной работе.

Литература

  1. Рихтер Дж., Программирование серверных приложений для Microsoft Windows 2000. СПб.: Питер; М.: Издательско-торговый дом, 2001.

  2. http://www.vsokovikov.narod.ru/New_MSDN_API/Menage_files/fn_createfile.htm

  3. http://www.vsokovikov.narod.ru/New_MSDN_API/Menage_files/fn_readfile.htm

  4. http://www.vsokovikov.narod.ru/New_MSDN_API/Synchronization/str_overlapped.htm

  5. http://pblog.ru/?p=74

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

  7. MSDN Library for Visual Studio 2008

ПРИЛОЖЕНИЕ А