Операционная система MS-DOS© Александр Фролов, Григорий ФроловТом 1, книга 3, М.: Диалог-МИФИ, 1992. 3.1. Получение справочной информацииПрежде чем мы начнем обзор функций получения справочной информации о состоянии и параметрах дисковой подсистемы, введем понятие текущего диска и текущего каталога. Если вы запускаете программу, которая находится в каком-либо каталоге на одном из дисков, то эти диск и каталог становятся текущими для MS-DOS. Это можно понимать в том смысле, что программе не требуется каждый раз при работе с файлами указывать требуемый диск или каталог. В любой момент времени программа может узнать текущие диск или каталог, а также заменить их. Для этого она должна использовать специальные функции прерывания INT 21h. Для установки текущего диска можно
использовать функцию 0Eh, которая имеет
следующий формат вызова:
Для того чтобы узнать номер текущего дисковода,
программа может воспользоваться функцией 19h:
Функция 3Bh предназначена для установки
текущего каталога:
Буфер пути может иметь максимальный размер 64 байта. Он должен содержать путь в формате ASCIIZ, т.е. строку, закрытую двоичным нулем, например: "path\dirname",0. Строка не должна содержать литеры, обозначающие диск. Если текущим должен стать корневой каталог, строка должна состоять только из одного двоичного нуля. Для того чтобы узнать текущий каталог, вы
можете воспользоваться функцией 47h:
Буфер должен иметь размер не менее 64 байтов, текущий каталог возвращается в формате ASCIIZ без литеры, обозначающей диск. Если текущим является корневой каталог, регистровая пара DS:SI будет указывать на нулевую строку (состоящую из одного двоичного нуля). Функции MS-DOS могут помочь вам в получении информации, необходимой для организации доступа к диску на уровне секторов и кластеров. При этом вы будете избавлены от необходимости читать в память и анализированть содержимое загрузочного сектора логического диска. Информация о таблице размещения файлов FAT
для текущего диска может быть получена с помощью
функции 1Bh прерывания INT 21h, имеющего
следующий формат:
Дополнительно эта функция возвращает информацию об общем количестве кластеров на диске, размере кластера в секторах и размере сектора в байтах. Для версий MS-DOS, более ранних, чем 2.0, регистровая пара DS:BX указывала на FAT, считанный в память. Более поздние версии операционной системы могут содержать по этому адресу только часть таблицы размещения файлов. Для получения аналогичной информации не о текущем, а о любом диске, используйте функцию 1Ch. Эта функция полностью аналогична предыдущей, за исключением того, что в регистре DL должен быть указан код дисковода: 0 - текущий, 1 - А:, 2 - В: и т.д. Эта функция доступна в MS-DOS версии 2.0 и в более поздних версиях. Если вас интересует размер свободного места на
диске, вы можете его узнать с помощью функции 36h,
имеющей следующий формат:
Эта функция возвращает в регистре AX число 0FFFFh, если вы неправильно указали номер дисковода. При обсуждении векторной таблицы связи мы рассказывали о блоках управления устройствами DDCB. Поле dev_cb векторной таблицы связи содержит FAR-адрес цепочки этих блоков. Приведем еще раз формат блока DDCB. Напомним,
что он изменяется в зависимости от версии DOS. Для
версий 2.х и 3.х блок DDCB имеет следующий формат:
Формат блока DDCB для DOS версии 4.х:
Файл sysp.h содержит определение типа DDCB для MS-DOS версии 4.х: /* Блок управления устройством DOS */ #pragma pack(1) typedef struct _DDCB_ { unsigned char drv_num; unsigned char drv_numd; unsigned sec_size; unsigned char clu_size; unsigned char clu_base; unsigned boot_siz; unsigned char fat_num; unsigned max_dir; unsigned data_sec; unsigned hi_clust; unsigned char fat_size; char reserv1; unsigned root_sec; void far *drv_addr; unsigned char media; unsigned char acc_flag; struct _DDCB_ far *next; unsigned reserv2; unsigned built; } DDCB; #pragma pack() При описании векторной таблицы связи мы
приводили примеры использования блоков DDCB.
Для получения адреса блока DDCB конкретного
дисковода можно воспользоваться
недокументированной функцией 32h. Она имеет
следующий формат вызова:
Для получения адреса блока DDCB текущего диска можно воспользоваться недокументированной функцией 1Fh, которая имеет формат, аналогичный функции 32h, за исключением того, что не надо задавать номер дисковода в регистре DL. Какая еще полезная информация может быть получена при использовании функций MS-DOS? С помощью функции 33h программа может
проверить или установить флаг Ctrl-Break и узнать
номер диска, с которого выполнялась загрузка
операционной системы:
Сведения о диске, который был использован для загрузки операционной системы, могут понадобиться вам для поиска файла, содержащего командный интерпретатор или программу DOSSHELL. Состояние флага Ctrl-Break влияет на возможность прервать выполнение программы нажатием комбинации клавиш Ctrl-Break или Ctrl-C. Если флаг находится в состоянии OFF, DOS проверяет эту комбинацию клавиш только при вызове функций стандартного ввода/вывода на консоль, принтер и последовательный порт. Если флаг установлен в состояние ON, комбинация клавиш проверяется и при вызове других функций MS-DOS. Если операционная система зафиксировала нажатие указанной комбинации клавиш, она выполняет прерывание INT 23h, которое завершает работу текущей программы. Функция 2Fh возвращает в регистровой паре ES:BX адрес текущей области DTA (Disk Transfer Area), которая используется при поиске файлов в каталогах. Функция 54h позволяет программе узнать текущее состояние флага проверки записывающейся на диск информации. В регистре AL эта функция возвращает текущее состояние флага. Если содержимое регистра равно 1, операционная система после записи сектора считывает его для проверки. Разумеется, такая проверка снижает скорость работы программы. Если после вызова функции регистр AL содержит 0, проверка записи не выполняется. Для установки флага проверки записи можно использовать функцию 2Eh. Перед вызовом функции в регистр AL необходимо занести новое значение флага проверки: 0 - проверка не нужна; 1 - должна выполняться проверка записанной информации. Стандартные библиотеки трансляторов Microsoft QC 2.5 и C 6.0 содержат несколько функций, облегчающих получение справочной информации о состоянии дисковой подсистемы. Функция _dos_getdiskfree() использует функцию 36h для получения информации о диске. Файл dos.h содержит описание этой функции: unsigned _dos_getdiskfree(unsigned drive, struct diskfree_t *diskspace); Параметр drive задает номер используемого дисковода: 0 - текущий, 1 - А:, и т.д. Информация возвращается в структуре diskfree_t, которая определена в файле dos.h: struct diskfree_t { unsigned total_clusters; unsigned avail_clusters; unsigned sectors_per_cluster; unsigned bytes_per_sector; }; В этой структуре:
Для получения номера текущего диска и для установки номера текущего диска можно использовать, соответственно, функции _dos_getdrive() и _dos_setdrive(). Функция _dos_getdrive() имеет формат: void _dos_getdrive(unsigned *drive); Эта функция пользуется функцией 19h для получения номера текущего диска, который записывается по адресу, задаваемому параметром. Значение 1 соответствует диску А:, 2 - В:, и т.д. Функция _dos_setdrive() предназначена для установки текущего диска и может быть использована для определения общего числа дисков в системе: void _dos_setdrive(unsigned drive, unsigned *drivecount); Параметр drive опеределяет текущий диск (1 - А:, и_т.д.), по адресу, задаваемому вторым параметром, функция записывает общее количество логических дисков, установленных в системе. Функция _dos_setdrive() использует функцию 0Eh прерывания INT 21h. Для иллюстрации способов использования функций _dos_getdrive(), _dos_setdrive(), _dos_getdiskfree() мы составили следующую программу: #include <dos.h> #include <bios.h> #include <conio.h> #include <stdio.h> void main(void); void main(void) { struct diskfree_t dinfo; unsigned drive, drivecount; printf("\n" "\nОпределение параметров текущего логического диска" "\n (C)Фролов А., 1991" "\n"); // Определяем номер текущего диска _dos_getdrive(&drive); // Выводим на экран литеру текущего диска printf("\nТекущий диск: %c:\n", 'A' + drive - 1); // Вызываем функцию установки текущего диска. // Мы не изменяем текущий диск, вызов этой функции // нужен нам для определения количества установленных // в системе логических дисков _dos_setdrive(drive, &drivecount); // Получаем характеристики текущего диска _dos_getdiskfree(drive, &dinfo); printf("\nОбщее количество кластеров на диске: %d" "\nКоличество свободных кластеров: %d" "\nКоличество секторов в кластере: %d" "\nКоличество байтов в секторе: %d" "\nРазмер диска в байтах: %ld" "\n", dinfo.total_clusters, dinfo.avail_clusters, dinfo.sectors_per_cluster, dinfo.bytes_per_sector, (long)dinfo.avail_clusters * dinfo.sectors_per_cluster * dinfo.bytes_per_sector ); printf("\nКоличество логических дисков: %d" "\n", drivecount); } |