Автор работы: Пользователь скрыл имя, 25 Марта 2014 в 14:49, лекция
Конспект лекций содержит описание технологии системного программирования под Windows с использованием функций Win32 API. В первой части конспекта лекций рассмотрены особенности архитектуры ОС Windows, специфика интерфейса прикладного программирования Win32, структура приложений для Windows. Подробно рассмотрены API функции и основные структуры данных для работы с дисками, каталогами, файлами. Отдельная глава посвящена структурной обработке исключений SEH.
Для получения информации о разбивке диска на сектора и кластеры может быть использована функция GetDiskFreeSpace(), которая, кстати, что следует из названия функции, помимо информации о разбивке тома, возвращает и информацию о свободном пространстве на диске.
BOOL GetDiskFreeSpace(
LPCTSTR lpRootPathName,
LPDWORD lpSectorsPerCluster,
LPDWORD lpBytesPerSector,
LPDWORD lpNumberOfFreeClusters,
LPDWORD lpTotalNumberOfClusters
Если внимательно посмотреть на аргументы этой функции, то сразу становится ясно, какие аргументы требуются для этой функции и какие данные она возвращает.
Первый аргумент, lpRootPathName, указывает на наименование корневой директории того диска, информацию о котором мы хотим получить. Если этот параметр равен NULL, используется корневая директория текущего диска.
Второй аргумент, lpSectorsPerCluster, указывает на двойное слово, в которое система запишет количество секторов в одном кластере.
Аргумент третий, lpBytesPerSector, является указателем на двойное слово, в которое будет записано количество байтов в одном секторе.
Четвёртый аргумент, lpNumberOfFreeClusters, содержит указатель на двойное слово, предназначенное для записи в него количества свободных кластеров на диске.
И, наконец, последний аргумент, lpTotalNumberOfClusters, указывает на двойное слово, в которое система запишет общее число кластеров на диске.
Если возвращённое функцией значение равно TRUE, то это означает, что функция завершила свою работу нормально. Если же функция вернула FALSE, то это является признаком того, что при выполнении функции возникла ошибка.
Возможности файловых систем не ограничиваются последовательной обработкой; они также могут обеспечивать прямой доступ, блокировку файлов, работу с каталогами и управление атрибутами файлов.
Windows поддерживает для каждого открытого файла указатель файла, обозначающий позицию текущего байта в файле. Каждая следующая операция WriteFile или ReadFile начинает последовательное перемещение данных в файл или из файла с этой позиции и увеличивает указатель файла на количество переданных байтов. При открытии файла функцией CreateFile указатель обнуляется, указывая на начало файла, и продвигается вперед с каждой последующей операцией чтения или записи. Первое, что необходимо для прямого доступа к файлу, - это возможность установить указатель файла на произвольную позицию. Для этого предназначена функция SetFilePointer.
DWORD SetFilePointer (HANDLE hFile, LONG lDistanceToMove,
PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod)
Возвращаемое значение: младшая часть (DWORD без знака) нового указателя файла. Старшая часть нового указателя передается значению DWORD, на которое указывает lpDistanceToMoveHigh (если это не пустой указатель). В случае ошибки функция возвращает значение 0x FFFFFFFF.
Параметры функции SetFilePointer:
hFile – дескриптор открытого файла с доступом для чтения или записи (или для обеих операций).
lDistanceToMove - значение, на которое перемещается указатель (типа LONG со знаком), или позиция файла (без знака), в зависимости от значения dwMoveMethod.
lpDistanceToMoveHigh указывает на старшую часть значения перемещения. Если этот указатель равен NULL, функция может работать только с файлами, длина которых не превышает 232 – 2. Этот параметр используется также для возврата старшей части указателя файла. Младшая часть – это возвращаемое значение функции.
dwMoveMetod определяет один из следующих режимов перемещения:
Эту функцию можно применять для определения длины файла, указывая нулевое перемещение с конца файла.
Узнать размер файла можно по возвращаемому значению SetFilePointer, задав перемещение на ноль байтов с конца. Для этого также существует специальная функция.
DWORD GetFileSize (HANDLE hFile, LPDWORD lpdwFileSizeHigh)
Возвращаемое значение: младший компонент размера файла. Значение 0xFFFFFFFF указывает на возможную ошибку. Старшие 32 разряда размера файла находятся в двойном слове, на которое указывает второй параметр функции. Функция требует, чтобы файл имел открытый дескриптор, который передается функции в качестве первого параметра.
Функция SetEndOfFile изменяет размер файла, определяя его длину по текущему значению указателя файла. Файл может быть расширен или укорочен. При расширении содержимое добавленной области не определено.
В системе FAT файлы не инициализируются автоматически нулевыми значениями. Согласно документации Microsoft, содержимое файла нельзя предсказать, и это подтверждается экспериментально. Поэтому, если инициализация требуется для нормальной работы, приложения должны инициализировать файл последовательностью операций WriteFile. В NTFS файлы инициализируются, поскольку уровень безопасности С2, который обеспечивается в Windows 2000/NT, требует, чтобы содержимое удаленного файла нельзя было прочесть.
Функция SetEndOfFile не единственный способ расширения файла. Его также можно расширить последовательными операциями записи, но это приведет к более фрагментированному размещению файла, тогда как SetEndOfFile позволяет операционной системе выделять большие непрерывные блоки дискового пространства.
В каталоге можно искать файлы и другие каталоги, удовлетворяющие указанному образцу имени, а также получать атрибуты файлов. Для этого необходим дескриптор поиска, который возвращается функцией FindFirstFile. Для получения нужных файлов служит функция FindNextFile, а для завершения поиска – FindClose.
HANDLE FindFirstFile (LPCSTSTR lpszSearchFile,
LPWIN32_FIND_DATA lpffd)
Возвращаемое значение: дескриптор поиска; в случае неудачи – INVALID_HANDLE_VALUE.
Функция FindFirstFile ищет соответствие имени как среди файлов, так и среди подкаталогов. Возвращаемый дескриптор используется в последующем поиске.
Параметры функции:
Структура WIN32_FIND_DATA определена следующим образом:
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];
} WIN32_FIND_DATA;
dwFileAttributes можно
проверить на соответствие
Часто требуется найти в каталоге файлы, имена которых удовлетворяют образцу, содержащему подстановочные знаки ? и *. Для этого нужно получить из FindFirstFile дескриптор поиска, который содержит информацию об искомом имени, и вызвать функцию FindNextFile.
BOOL FindNextFile (HANDLE hFindFile,
LPWIN32_FIND_DATA lpffd)
Эта функция возвращает значение FALSE либо при недопустимых параметрах, либо если соответствие данному образцу уже нельзя найти. В последнем случае GetLastError возвращает ERROR_NO_MORE_FILES.
Когда поиск закончен, следует закрыть дескриптор поиска. Для этого нельзя использовать функцию CloseHandle. Для закрытия дескриптора поиска предназначена функция
BOOL FindClose (HANDLE hFindFile)
Функция GetFileInformationByHandle позволяет получить ту же информацию для определенного файла, указав его открытый дескриптор.
Функции FindFirstFile и FindNextFile позволяют получить следующую информацию об атрибутах файла: флаги атрибутов, три штампа времени и размер файла. Для работы с атрибутами есть несколько других функций, которые могут работать непосредственно с дескриптором открытого файла без просмотра каталога или указания имени файла. Функции GetFileSize и SetEndOfFile уже были рассмотрены. Другие функции служат для получения остальных атрибутов. Например, для получения штампов времени открытого файла предназначена следующая функция:
BOOL GetFileTime (HANDLE hFile, LPFILETIME lpftCreation,
LPFILETIME lpftLastAccess,
LPFILETIME lpftLastWrite)
Значения времени здесь и в структуре WIN32_FIND_DATA - 64-разрядные целые числа без знака, указывающие 100-наносекундных единиц (107 единиц в секунду), прошедших с исходного времени (1 января 1601 г.), в форме всеобщего скоординированного времени (Universal Coordinataed Time – UTC). Существует несколько удобных функций работы со временем.
Функция GetFileType позволяет различать дисковые файлы, символьные файлы (фактически это устройство наподобие принтеров и консолей) и каналы. Файл также указывается своим дескриптором.
Функция
DWORD GetFileAttributes (LPCTSTR lpszFileName)
возвращает по указанному имени файла и каталога только атрибуты. В случае неудачи возвращает 0хFFFFFFFF.
Атрибуты можно проверить на соответствие комбинациям определенных значений. Значения атрибутов могут быть следующими:
FILE_ATTRIBUTE_DIRECTIRY
FILE_ATTRIBUTE_NORMAL
FILE_ATTRIBUTE_READONLY
FILE_ATTRIBUTE_TENPORARY
Функция SetFileAttribute изменяет эти атрибуты в указанном по имени файле.
Следующая функция создает имена для временных файлов.
UNIT GetTempFileName (LPCTSTR lpszPath,
LPCTSTR lpszPrefix,
UNIT uUnique,
LPCTSTR plszTempFile)
Эта функция выдает уникальное имя файла с расширением .tmp в указанном каталоге и может создавать такой файл. Параметры функции:
lpszPath – каталог для временного файла. Символ «.» обычно обозначает текущий каталог. Можно также указать каталог, предназначенный для временных файлов. Его имя выдает функция Win32 GetTempPath.
lpszPrefix – префикс имени временного файла; допускаются только символы ANSI.
uUnique обычно
равно нулю; в этом случае функция
генерирует уникальное
plszTempFile указывает на буфер, который содержит имя временного файла. Длина буфера в байтах должна быть не меньше MAX_PATH. Полученное в результате полное имя – конкатинация пути, префикса, четырехразрядного шестнадцатеричного числа и расширения .tmp.
Важный вопрос в любой системе с несколькими процессами – координация и синхронизация доступа к совместно используемым объектам, например, файлам.
Win32 может блокировать файлы полностью или частично, т.е. так, чтобы никакой другой процесс (выполняемая программа) не мог обращаться к блокированной области файла. Заблокированный файл может быть открыт только для чтения (совместный доступ) или для чтения и записи (монопольный доступ). Следует подчеркнуть, что блокировка связана с процессом.
Функция LockFile блокирует область байтов в открытом файле для совместного (несколько читающих процессов) или монопольного (один читающий и пишущий процесс) доступа:
BOOL LockFile(HANDLE hFile,
DWORD dwFileOffsetLow,
DWORD dwFileOffsetHigh,
DWORD nNumberOfBytesToLockLow,
DWORD nNumberOfBytesToLockHigh)
Параметры функции:
hFile – дескриптор открытого файла; должен иметь права доступа либо GENERIC_READ, либо GENERIC_READ и GENERIC_WRITE.
DWORD dwFileOffsetLow,DWORD dwFileOffsetHigh младшие и старшие 32 разряда смещения той части файла, которую необходимо блокировать .
DWORD nNumberOfBytesToLockLow и DWORD nNumberOfBytesToLockHigh младшие и старшие 32 разряда числа, определяющего размер блокируемой области файла в байтах.
Разблокировка производится функцией:
UnlockFile (HANDLE hFile,
DWORD dwFileOffsetLow,
DWORD dwFileOffsetHigh,
DWORD nNumberOfBytesToLockLow,
DWORD nNumberOfBytesToLockHigh)
Назначение параметров этой функции аналогично параметрам функции LockFile.
При блокировке следует учитывать следующее.
- Снятие блокировки относится точно к той же области, что и предшествующая блокировка. Не допускается разблокировать две заблокированные ранее области или часть заблокированной области. При попытке разблокировать область, которая не точно соответствует существующей блокировке, функция вернет значение FALSE, и системное сообщение укажет, что блокировки не существует.
Структурная обработка исключительных ситуаций (Structured Exception Handling — SEH) в Win32 представляет собой надежный механизм, позволяющий приложениям отвечать на неожиданные события, такие как исключительные ситуации при адресации, сбои при выполнении арифметических операций и системные ошибки. Кроме того, SEH делает возможным завершение программы из любой точки в блоке кода, а также автоматически выполняет указанные программистом действия и восстановление при ошибках.
Главное, почему Microsoft ввела в Windows подержку SEH, было ее стремление упростить разработку операционной системы и повысить ее надежность. Разработчику же использование SEH позволит повысить надежность создаваемых приложений.
Основная нагрузка по поддержке SEH ложится на компилятор, а не на операционную систему. Он генерирует специальный код на входах и выходах блоков исключений, создает таблицы вспомогательных структур данных для поддержки SEH и предоставляет функции обратного вызова, к которым система могла бы обращаться для прохода по блокам исключений. Компилятор отвечает и за формирование стековых фреймов и другой внутренней информации, используемой операционной системой.
Информация о работе Системное программирование в среде Win32