- •Методические указания
- •Краматорск, дгма, 2013
- •Содержание
- •Лабораторная работа № 1
- •Теоретические сведения
- •Ход работы
- •Индивидуальное задание
- •Теоретические сведения
- •Литература
- •Лабораторная работа № 2
- •Ход работы
- •Индивидуальное задание
- •Лабораторная работа № 3
- •Теоретические сведения
- •Учебный проект для работы с событиями
- •Учебный проект для работы с событиями
- •Ход работы
- •Индивидуальное задание
- •Лабораторная работа № 4
- •Теоретические сведения
- •Учебный проект
- •Ход работы
- •Индивидуальное задание
- •Лабораторная работа № 4
- •Теоретические сведения
- •Учебный проект
- •Ход работы
- •Индивидуальное задание
- •Лабораторная работа № 6
- •Теоретические сведения
- •Учебный проект
- •Ход работы
- •Индивидуальное задание
- •Лабораторная работа № 7
- •Теоретические сведения
- •Ход работы
- •Лабораторная работа № 8
- •Теоретические сведения
- •Атрибуты контекста отображения
- •Цвет фона
- •Режим фона
- •Режим рисования
- •Цвет текста
- •Расстояние между буквами
- •Цветовая палитра
- •Начальные координаты кисти
- •Режим закрашивания многоугольников
- •Текущая позиция пера
- •Изображение bitmap
- •Режим растяжения
- •Область ограничения
- •Режим отображения
- •Начало системы координат для окна
- •Начало системы физических координат
- •Масштаб осей для окна
- •Масштаб осей физических координат
- •Учебный проект
- •Ход работы
- •Лабораторная работа № 9
- •Теоретические сведения
- •Ход работы
- •Лабораторная работа № 10
- •Теоретические сведения
- •Int (*Add)(int); // для адреса функции Add из dll
- •Int (*Sub)(int); // для адреса функции Sub из dll
- •Int *pCount; // для адреса переменной count из dll
- •Ход работы
- •Список рекомендованной литературы
- •Вопросы к экзамену по дисциплине «Операционные системы»
Индивидуальное задание
Реализовать задание, исходя из соответствующей схемы создания и взаимодействия потоков, процессов и буфера обмена.
Отчет по лабораторной работе должен содержать тему, цель, содержание индивидуального задания, листинг программы, скрин-шот результатов расчета.
Лабораторная работа № 7
Асинхронный ввод-вывод в режиме пользователя
Цель: Получить навыки в следующих предметных областях:
работа с файлами в режиме ввода-вывода с перекрытием (input/output overlapped).
Теоретические сведения
Функция CreateFile
Функция создаёт указатель на новое устройство типа:
Файл
Канал
mailslot (почтовый канал)
коммуникационный ресурс (например COM порт)
дисковые устройства
консоли
директории (открывает их)
Все эти функции описаны в одном файле windows.h.
Описание:
1 2 3 4 5 6 7 8 9 |
HANDLE CreateFile( LPCTSTR lpFileName, // Указатель на имя файла (устройства) DWORD dwDesiredAccess, //Параметры доступа DWORD dwShareMode, //Разделяемый доступ LPSECURITY_ATTRIBUTES lpSecurityAttributes, //безопасность DWORD dwCreationDistribution,// Описание DWORD dwFlagsAndAttributes, // Атрибуты файла HANDLE hTemplateFile // Файл шаблона ); |
Файл создается следующим образом:
1 2 3 4 5 6 7 |
{ Handle FileHandle; FileHandle=CreateFile("file1.txt",GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 0); CloseHandle(FileHandle); } |
Теперь рассмотрим используемые параметры:
параметры GENERIC_READ и GENERIC_WRITE определяют доступ на чтение и запись. Однако можно указать что-то одно в зависимости от ваших потребностей. Если в качестве этого параметра указать 0, то в этом случае функция отработает успешно, однако никакого доступа к файлу не получит. Этот вариант удобно использовать для теста существования файла.
параметры FILE_SHARE_WRITE or FILE_SHARE_READ — общий доступ на чтение и запись к данному файлу. То есть файл будет доступен при одновременном использовании несколькими процессами.
следующий параметр — атрибут безопасности неопределен. То есть все дескрипторы будут доступны дочерним процессам вашего приложения.
параметр CREATE_NEW указывает на создание нового файла. Если файл с заданным именем существует, то будет возвращен код ошибки. Если использовать параметр CREATE_ALWAYS, то в этом случае, если файл существует, то он будет перезаписан.
параметр FILE_ATTRIBUTE_NORMAL определяет файлу стандартные атрибуты. А если указывать флаг FILE_FLAG_OVERLAPPED, то файл будет доступен в асинхронном режиме.
так как мы не используем шаблоны, то в качестве этого параметра указываем ноль.
Функция OpenFile
Данная функция, по сути своей, предназначена для открытия файлов или устройств. Функция OpenFile в случае успеха возвращает дескриптор (указатель) открываемого файла. В случае неудачи мы получим в качестве дескриптора значение INVALID_HANDLE_VALUE.
1 2 3 4 5 |
HFILE WINAPI OpenFile( LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle ); |
Теперь рассмотрим используемые параметры:
в качестве первого параметра указывается имя открываемого файла.
вторым параметром является специальная структура открываемого файла, в которую заносятся сведения о файле.
3-й параметр представляет собой совокупность флагов для работы с файлом.
Собственно, как открыть файл:
1 2 3 4 5 6 |
{ Handle FileHandle; FileHandle= OpenFile("Settings.ini", Buf, OF_Create | OF_READWRITE | OF_SHARE_EXCLUSIVE); CloseHandle(FileHandle); } |
В данном примере стоит уделить внимание флагам. Первые 2 из которых определяют доступ к файлу, а флаг OF_SHARE_EXCLUSIVE сообщает системе, что доступ к этому файлу запрещен до тех пор, пока указатель на этот файл не освободится.
Функция ReadFile
Данная функция предназначена для чтения файлов или с устройств ввода/вывода. В случае успешного выполнения операции чтения, возвращается логическое значение true, иначе false. А функция GetLastError вернет ERROR_HANDLE_EOF.
1 2 3 4 5 6 7 |
BOOL ReadFile(HANDLE hFile, //собственно указатель на файл LPVOID lpBuffer, // указатель на буфер - куда записываем считанные данные DWORD nNumberOfBytesToRead, //объем считываемых данных, не может превышать размер буфера LPDWORD lpNumberOfBytesRead, //фактический размер считанных данных LPOVERLAPPED lpOverlapped // флаг режима доступа к файлу: // асинхронный (FILE_FLAG_OVERLAPPED) или синхронный // (NULL) ); |
Теперь рассмотрим рабочий пример:
1 2 3 4 5 6 7 |
{ Handle FileHandle; char Buf[1000]; ... ReadFile(FileHandle, Buf, sizeof(buf),NULL); ... } |
Функция WriteFile
Данная функция предназначена для записи в файл или устройство ввода/вывода. С ней все аналогично что и с функцией ReadFile(). В случае успешного выполнения операции чтения, возвращается логическое значение true, иначе false. А функция GetLastError вернет ERROR_HANDLE_EOF.
1 2 3 4 5 6 7 |
BOOL WriteFile(HANDLE hFile, //собственно указатель на файл LPVOID lpBuffer, // указатель на буфер - откуда записываем данные в файл DWORD nNumberOfBytesToWrite, //объем записываемых данных LPDWORD lpNumberOfBytesWrite, //фактический размер записанных данных LPOVERLAPPED lpOverlapped // флаг режима доступа к файлу: асинхронный(FILE_FLAG_OVERLAPPED) //или синхронный(NULL) ); |
Теперь рассмотрим рабочий пример:
1 2 3 4 5 6 7 |
{ Handle FileHandle; char Buf[1000]; ... ReadFile(FileHandle, Buf, sizeof(buf),NULL); ... } |
Функция CloseHandle
Эта функция достаточно проста. Выполняет действия по освобождению указателя на файл. Ее необходимость очевидна — чтобы не засорять память ненужными указателями и позволять работу с файлами другим процессам. В качестве ее единственного параметра передается указатель на ранее открытый файл.
Теперь рассмотрим рабочий пример:
1 2 3 4 5 6 7 |
{ Handle FileHandle; FileHandle= OpenFile("Settings.ini", Buf, OF_Create | OF_READWRITE | OF_SHARE_EXCLUSIVE); ... CloseHandle(FileHandle); } |
Функция DeleteFile
Эта функция так же не отличается особой сложностью. Данная функция удаляет файл, который указан в параметре. Функция возвращает значение true, если выполняется успешно. Иначе возвращает false, а код ошибки можно получить с помощью GetLastError.
1 2 3 |
BOOL WINAPI DeleteFile( LPCTSTR lpFileName // имя файла, который надо удалить ); |
Теперь рассмотрим рабочий пример:
1 2 3 4 5 6 7 |
{ ... DeleteFile("C:\Temp\test.txt");// если указать только // имя файла, то будет осуществлена попытка удалить файл из папки, откуда была запущена программа
... } |
Функция CopyFile
Основное назначение этой функции — копирование файла. В случае успеха возвращает true, иначе — false. Код ошибки можно получить с помощью GetLastError.
1 2 3 4 5 6 |
BOOL CopyFile( LPCTSTR lpExistingFileName,// Указатель на файл, который надо копировать LPCTSTR lpNewFileName, // Указатель на имя файла, куда надо копировать BOOL bFailIfExists //если указать true, то в случае существования такого файла, // произойдет ошибка, если false - то существующий файл будет перезаписан. ); |
Теперь рассмотрим рабочий пример:
1 2 3 4 5 6 |
{ ... CopyFile("C:\Temp\test1.txt","C:\Temp\test2.txt", true); // если указать только // имя файла, то все действия будут выполнены в папке из которой запущена программа ... } |
Функция FindFirstFile
Данная функция запускает поиск в указанной директории. Функция возвращает указатель на найденный файл, если нет, то возврат будет типа ERROR_NO_MORE_FILES.
1 2 3 4 |
HANDLE FindFirstFile( LPCTSTR lpFileName, // Строка, содержащая путь для поиска файлов. LPWIN32_FIND_DATA lpFindFileData // Информация о найденном файле ); |
Теперь рассмотрим параметры подробней:
lpFileName — строка, содержащая путь для поиска файла. Эта строка может указывать на конкретный файл типа ‘c:\filename.txt’ или может хранить шаблон ‘c:\*.*’. Если указывать шаблон, то это даёт возможность перечислить все файлы удовлетворяющие шаблону.
lpFindFileData — структура WIN32_FIND_DATA, в которую будут записаны сведения о найденном файле.
Рассмотрим структуру WIN32_FIND_DATA немного подробнее:
1 2 3 4 5 6 7 8 9 10 11 12 |
typedef struct _WIN32_FIND_DATA { DWORD dwFileAttributes; // Атрибуты файла FILETIME ftCreationTime; // Время создания FILETIME ftLastAccessTime; //Время последнего доступа FILETIME ftLastWriteTime; //Время последней записи в файл DWORD nFileSizeHigh; //Верхний байт размера файла DWORD nFileSizeLow; //Нижний байт размера файла DWORD dwReserved0; //Зарезервировано DWORD dwReserved1; //Зарезервировано TCHAR cFileName[ MAX_PATH ]; //Имя файла TCHAR cAlternateFileName[ 14 ]; //Имя файла для отображения в DOS (8:3) } WIN32_FIND_DATA; |
Атрибутами файла может быть комбинация из флагов:
FILE_ATTRIBUTE_ARCHIVE — архивный
FILE_ATTRIBUTE_COMPRESSED — сжатый
FILE_ATTRIBUTE_HIDDEN — скрытый
FILE_ATTRIBUTE_NORMAL — нормальный
FILE_ATTRIBUTE_OFFLINE — данные файла недоступны
FILE_ATTRIBUTE_READONLY — только для чтения
FILE_ATTRIBUTE_SYSTEM — системный
FILE_ATTRIBUTE_TEMPORARY — временный
Размер файла разложен на два байта. Чтоб получить полный размер файла нужно выполнить действие (FInfo.nFileSizeHigh * MAXDWORD) + FInfo.nFileSizeLow. Это не самый эффективный (эффективнее сдвигать), но самый понятный способ.
Теперь рассмотрим рабочий пример:
1 2 3 4 5 6 7 |
{ WIN32_FIND_DATA sss; HANDLE f; f = FindFirstFile("C:\*.*", &sss); ... FindClose(f); } |
Функция FindNextFile
Данная функция продолжает поиск начатый функцией FindFirstFile(). Если очередной файл найден, то функция возвращает значение true, иначе возврат будет типа ERROR_NO_MORE_FILES.
1 2 3 4 |
BOOL FindNextFile( HANDLE hFindFile, // Указатель на файл из предыдущего поиска LPWIN32_FIND_DATA lpFindFileData // Информация об очередном найденном файле ); |
Со вторым параметром всё ясно, из описания функции FindFirstFile. А вот первый — это указатель на файл из предыдущего поиска. Он нужен, чтобы функция FindNextFile знала, на каком файле был остановлен поиск и какой надо найти следующим.
Теперь рассмотрим рабочий пример:
1 2 3 4 5 6 7 8 9 10 |
{ WIN32_FIND_DATA sss; HANDLE f; f = FindFirstFile("C:\*.*", &sss); if(f != INVALID_HANDLE_VALUE) do{ ... }while(FindNextFile(f,&sss)); FindClose(f); } |
Функция GetFileSize
Данная функция определяет размер файла, на который ссылается переданный указатель. Если размер файла меньше 4 Гб, то функция возвращает размер файла. Если размер файла больше 4Гб, то размер файла записан во втором параметре. В случае возникновения исключения будет возвращено значение типа INVALID_FILE_SIZE.
1 2 3 4 5 |
DWORD GetFileSize( HANDLE hFile, // Указатель на файл LPDWORD lpFileSizeHigh // старший байт размера файла, в качестве // этого параметра можно указать NULL ); |
Теперь рассмотрим рабочий пример:
1 2 3 4 5 6 7 |
{ DWORD FileSize; Handle f; ... FileSize=GetFileSize(f,NULL); ... } |
Асинхронный ввод-вывод
Асинхронный ввод-вывод реализован в некоторых UNIX-системах (есть стандарт POSIX для таких операций). Одна из наиполнейших реализаций этой технологии доступная также в системах линии Wіndows ХР, где ее называют вводом-выводом с перекрытием (overlapped І/O). Основная идея здесь заключается в том, что поток, который начал выполнять ввод-вывод, не блокируют до его завершения. Асинхронный ввод-вывод сводится к выполнению таких действий.
Поток выполняет системный вызов асинхронного ввода или вывода, который ставит операцию ввода-вывода в очередь и немедленно возвращает управление.
Поток продолжает выполнение параллельно с операцией ввода-вывода.
Когда операция ввода-вывода завершается, поток получает об этом сообщение.
Операция может быть прервана до своего завершения.
Основным подходом к получению сообщения о завершении асинхронного ввода-вывода является выполнение операции ожидания завершения ввода-вывода. При этом поток приостанавливают до завершения асинхронной операции. После продолжения выполнения потока можно получить информацию о результате выполнения операции. Укажем, что только на это время буфер, указатель на который был передан в операцию асинхронного ввода, заполнится считанными данными.
В Wіn32 АРЕ применяется следующий подход: для асинхронного ввода-вывода можно использовать стандартные функции файлового ввода и вывода ReadFіle() и WrіteFіle(), если в них передается последним параметром указатель на специальную структуру типа OVERLAPPED. При этом файл должен быть открыт с включенным флажком, который разрешает асинхронные операции. Для ожидания завершения ввода-вывода используют универсальную функцию ожидания, например WaіtForSіngleObject(). В простейшем случае она должна ожидать на файловом дескрипторе, для которого было выполнено ввод или вывод. Для получения результата надо использовать функцию GetOverlappedResult(), для прерывания ввода-вывода – CancelIO(). Приведем схему использования асинхронного ввода-вывода в Wіn32 АРI.
// структура - индикатор асинхронной операции
OVERLAPPED ov = { 0 };
// открыть файл с флажком асинхронного ввода-вывода
HANDLE fh = CreateFіle (.... FІLE_FLAG_OVERLAPPED,...);
// асинхронную операцию чтения задают передачей указателя на структуру ov
ReadFіle (fh, buf, sіzeof(buf), &sіze, &ov);
// ... другие действия, здесь buf пока использовать нельзя
WaіtForSіngleObject (fh, ІNFІNІTE); // ожидание завершения операции
// здесь можно использовать buf
// получение результата операции
GetOverlappedResult (fh, &ov, &nread, FALSE);
