Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

MS-DOS для программиста

© Александр Фролов, Григорий Фролов
Том 19, М.: Диалог-МИФИ, 1995, 253 стр.

[Назад] [Содеожание] [Дальше]

3.1. Получение справочной информации

В этом разделе мы опишем наиболее нужные, на наш взгляд, функции MS-DOS, предназначенные для получения справочной информации о состоянии дисковой системы.

Текущий диск и текущий каталог

В любой момент времени программа может определить текущий диск или текущий каталог, а также сменить текущий диск или текущий каталог. Для этого она должна использовать специальные функции прерывания INT 21h .

Для того чтобы узнать номер текущего диска, программа может воспользоваться функцией 19h:

На входе: AH 19h
На выходе: AL Номер текущего устройства НГМД или НМД (0 - А:, 1 - В:, и т. д.).

Для установки текущего диска можно использовать функцию 0Eh, которая имеет следующие параметры вызова:

На входе: AH 0Eh
DL Номер устройства НГМД или НМД (0 - А:, 1 - В:, и т. д.)
На выходе: AL Общее количество дисковых устройств в системе. Эта величина соответствует параметру LASTDRIVE из файла CONFIG.SYS

Для того чтобы узнать текущий каталог, вы можете воспользоваться функцией 47h:

На входе: AH 47h
DL Номер устройства НГМД или НМД (0 - текущий, 1 - А:, 2 - В:, и т. д.)
DS:SI Адрес буфера для записи пути текущего каталога
На выходе: AX Код ошибки, если установлен флаг переноса CF

Буфер должен иметь размер не менее 64 байт. Функция 47h возвращает текущий каталог в формате ASCIIZ (то есть строку, закрытую двоичным нулем, например: "path\dirname",0) без символа, обозначающего диск. Если текущим является корневой каталог, регистровая пара DS:SI будет указывать на нулевую строку (состоящую из одного двоичного нуля).

Функция 3Bh предназначена для установки текущего каталога:

На входе: AH 3Bh
DL Номер устройства НГМД или НМД (0 - текущий, 1 - А:, 2 - В:, и т. д.)
DS:DX Адрес буфера, содержащего путь к каталогу, который должен стать текущим
На выходе: AX Код ошибки, если установлен флаг переноса CF

Буфер может иметь максимальный размер 64 байт. Он должен содержать путь в формате ASCIIZ. Строка не должна содержать символ, обозначающий диск. Если текущим должен стать корневой каталог, строка должна состоять только из одного двоичного нуля.

Определение размера кластера и сектора

Функции MS-DOS могут помочь вам в получении информации, необходимой для организации доступа к диску на уровне секторов и кластеров. При этом вы будете избавлены от необходимости читать в память и анализировать содержимое загрузочного сектора логического диска.

Информация о таблице размещения файлов FAT для текущего диска может быть получена с помощью функции 1Bh прерывания INT 21h , имеющего следующие параметры вызова:

На входе: AH 1Bh
На выходе: DS:BX Адрес первого байта FAT . Это байт идентификации среды носителя данных, соответствует байту media в блоке параметров BIOS
DX Общее количество кластеров на диске
AL Количество секторов в одном кластере
CX Количество байт в одном секторе

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

Для старых версий MS-DOS регистровая пара DS:BX указывала на FAT , считанный в память. Более поздние версии операционной системы могут содержать по этому адресу только часть таблицы размещения файлов .

Для получения аналогичной информации не о текущем, а о любом диске, используйте функцию 1Ch. Эта функция полностью аналогична предыдущей, за исключением того, что в регистре DL должен быть указан номер НГМД или НМД: 0 - текущий, 1 - А:, 2 - В: и т. д.

Определение размера свободного пространства

Если вас интересует размер свободного места на диске, вы можете его узнать с помощью функции 36h:

На входе: AH 36h
DL Номер устройства НГМД или НМД (0 - текущий, 1 - А:, 2 - В:, и т. д.)
На выходе: AX Количество секторов в кластере или 0FFFFh, если был задан неправильный номер устройства
BX Количество свободных кластеров на диске
CX Количество байт в одном секторе
DX Общее количество кластеров на диске

Эта функция возвращает в регистре AX число 0FFFFh, если вы неправильно указали номер устройства.

Блок управления устройством DDCB

При обсуждении векторной таблицы связи в предыдущем томе "Библиотеки системного программиста" мы рассказывали о блоках управления устройствами DDCB . Поле dev_cb векторной таблицы связи содержит дальний адрес цепочки этих блоков.

Для получения адреса блока DDCB можно воспользоваться недокументированной функцией 32h:

На входе: AH 32h
DL Номер устройства НГМД или НМД (0 - текущий, 1 - А:, 2 - В:, и т. д.)
На выходе: AL 0, если был задан правильный номер устройства;
0FFh, если был задан неправильный номер устройства
DS:BX Адрес блока DDCB

Для получения адреса блока DDCB текущего диска можно также воспользоваться недокументированной функцией 1Fh, которая имеет формат, аналогичный функции 32h, за исключением того, что для нее не надо задавать номер устройства в регистре DL.

Флаг прерывания

С помощью функции 33h программа может проверить или установить флаг прерывания при помощи комбинации клавиш <Ctrl+Break> и, кроме того, узнать номер диска, с которого выполнялась загрузка операционной системы:

На входе: AH 33h
AL Код операции:
0 - Проверить текущее состояние флага прерывания при помощи комбинации клавиш <Ctrl+Break> ;
1 - Установить флаг прерывания при помощи комбинации клавиш <Ctrl+Break>;
5 - Определить номер диска, который был использован для загрузки операционной системы
DL Значение флага прерывания при помощи комбинации клавиш <Ctrl+Break> операции с кодом 1:0 - запретить прерывание,1 - разрешить прерывание
На выходе: DL Текущее состояние флага прерывания при помощи комбинации клавиш <Ctrl+Break> для операции с кодом 0; Номер диска, использованного для загрузки операционной системы для операции 5 (1 - А:, 2 - В:, и т. д.)

Сведения о диске, который был использован для загрузки операционной системы, могут понадобиться вам, например, для поиска файла командного интерпретатора.

Состояние флага прерывания при помощи комбинации клавиш <Ctrl+Break> влияет на возможность прервать выполнение программы. Если прерывание запрещено, MS-DOS проверяет эту комбинацию клавиш только при вызове функций стандартного ввода/вывода на консоль, принтер и последовательный порт. Если же прерывание разрешено, указанная комбинация клавиш проверяется и при вызове других функций MS-DOS. Если пользователь нажал комбинацию клавиш <Ctrl+Break>, операционная система выполняет прерывание INT 23h , которое завершает работу текущей программы.

Адрес области DTA

Функция 2Fh возвращает в регистровой паре ES:BX адрес текущей области DTA (Disk Transfer Area ), которая используется при поиске файлов в каталогах. Этот адрес необходим резидентным программам, о чем мы говорили в предыдущем томе "Библиотеки системного программиста".

Флаг проверки записи

Функция 54h позволяет программе узнать текущее состояние флага проверки записи информации на диск. В регистре AL эта функция возвращает текущее состояние флага.

Если содержимое регистра равно 1, после записи сектора операционная система считывает его для проверки. Разумеется, такая проверка снижает скорость работы программы. Если после вызова функции регистр AL содержит 0, проверка записи не выполняется.

Для установки флага проверки записи можно использовать функцию 2Eh. Перед вызовом функции в регистр AL необходимо занести новое значение флага проверки: 0 - проверка не нужна; 1 - должна выполняться проверка записанной информации.

Функции библиотеки Borland C++

Стандартная библиотека Borland C++ содержит несколько функций, облегчающих получение справочной информации о состоянии дисковой системы.

_dos_getdiskfree

Функция _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;
};

Поля этой структуры описаны ниже:

Поле Описание
unsigned total_clusters Общее количество кластеров на диске
unsigned avail_clusters Количество свободных кластеров
unsigned sectors_per_cluster Количество секторов, занимаемых одним кластером
unsigned bytes_per_sector Размер сектора в байтах

_dos_getdrive и _dos_setdrive

Для получения номера текущего диска и для установки номера текущего диска можно использовать, соответственно, функции _dos_getdrive и _dos_setdrive .

Функция _dos_getdrive имеет следующий прототип:

void _dos_getdrive (unsigned *drive);

Она пользуется функцией 19h для получения номера текущего диска, который записывается по адресу, задаваемому параметром drive. Значение 1 соответствует диску А:, 2 - В:, и т. д.

Функция _dos_setdrive предназначена для установки текущего диска и может быть использована для определения общего числа дисков в системе:

void _dos_setdrive (unsigned drive, unsigned *drivecount);

Параметр drive определяет текущий диск (1 - А:, и т. д.). В переменную, адрес которой передается через второй параметр, функция записывает общее количество логических дисков, установленных в системе. Функция _dos_setdrive использует функцию 0Eh прерывания INT 21h .

Программа DISKINF2

Для иллюстрации способов использования функций _dos_getdrive , _dos_setdrive и _dos_getdiskfree мы составили программу DISKINF2 (листинг 3.1).


Листинг 3.1. Файл diskinf2\diskinf2.cpp


#include <dos.h>
#include <bios.h>
#include <conio.h>
#include <stdio.h>

void main(void)
{
  struct diskfree_t dinfo;
  unsigned drive, drivecount;

  printf("\n"
    "\nОпределение параметров текущего логического диска"
    "\n  (C)Фролов А., 1995\n");

  // Определяем номер текущего диска
  _dos_getdrive (&drive);

  // Выводим на экран обозначение текущего диска
  printf("\nТекущий диск:                        %c:\n",
    'A' + drive - 1);

  // Вызываем функцию установки текущего диска.
  // Мы не изменяем текущий диск, вызов этой функции
  // нужен нам для определения количества установленных
  // в системе логических дисков
  _dos_setdrive (drive, &drivecount);

  // Получаем характеристики текущего диска
  _dos_getdiskfree (drive, &dinfo);

  printf("\nОбщее количество кластеров на диске: %u"
    "\nКоличество свободных кластеров:      %u"
    "\nКоличество секторов в кластере:      %u"
    "\nКоличество байт   в секторе:         %u"
    "\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);
}

[Назад] [Содеожание] [Дальше]