Операционная система MS DOS

Список управляющих блоков устройств


Поле dev_cb векторной таблицы связи содержит FAR-адрес цепочки блоков управления устройствами DOS (DOS Device Control Block) - DDCB. Блок DDCB строится операционной системой для каждого дискового устройства и содержит информацию о характеристиках этого устройства и указатель на заголовок драйвера, обслуживающего данное устройство.

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

Приведем формат блока DDCB для DOS версий 2.х и 3.х:



(0) 1 drv_num номер устройства (0 соответствует устройству А:, 1 - В: и т.д.)
(+1) 1 drv_numd дополнительный номер устройства внутри драйвера
(+2) 2 sec_size размер сектора в байтах
(+4) 1 clu_size число, на единицу меньшее количества секторов в кластере
(+5) 1 clu_base если содержимое этого поля не равно нулю, то для получения общего числа секторов в кластере надо возвести 2 в степень clu_base и получившееся число прибавить к clu_size
(+6) 2 boot_siz количество зарезервированных секторов (boot-сектора, начало корневого каталога)
(+8) 1 fat_num количество копий FAT
(+9) 2 max_dir максимальное число дескрипторов файлов в корневом каталоге (т.е. максимальное число файлов, которое может содержать корневой каталог на этом устройстве)
(+11) 2 data_sec номер первого сектора данных на диске (номер сектора, соответствующего кластеру номер 2)
(+13) 2 hi_clust максимальное количество кластеров (равно увеличенному на 1 количеству кластеров данных)
(+15) 1 fat_size количество секторов, занимаемых одной копией FAT
(+16) 2 root_sec номер первого сектора корневого каталога
(+18) 4 drv_addr FAR-адрес заголовка драйвера, обслуживающего данное устройство
(+22) 1 media байт описания среды носителя данных
(+23) 1 acc_flag флаг доступа, 0 означает, что к устройству был доступ
(+24) 4 next адрес следующего блока DDCB, для последнего блока в поле смещения находится число FFFF
    --------------- только для DOS 2.x -----------------
(+28) 2 dir_clu номер начального кластера текущего каталога (0 для корневого каталога)
(+30) 64 dir_path строка в формате ASCIIZ, содержащая путь к текущему каталогу
    ----- DOS 3.х ------
(+28) 2 reserv1 зарезервировано, обычно равно 0
(+30) 2 built число FFFF в этом поле означает, что блок DDCB был построен
<
Для DOS версии 4. х формат этого блока другой. Кроме того, изменилась его длина:

(0) 1 drv_num номер устройства (0 соответствует устройству А:, 1 - В: и т.д.)
(+1) 1 drv_numd дополнительный номер устройства внутри драйвера
(+2) 2 sec_size размер сектора в байтах
(+4) 1 clu_size число, на единицу меньшее количества секторов в кластере
(+5) 1 clu_base если содержимое этого поля не равно нулю, то для получения общего числа секторов в кластере надо возвести 2 в степень clu_base и получившееся число прибавить к clu_size
(+6) 2 boot_siz количество зарезервированных секторов (boot-сектора, начало корневого каталога)
(+8) 1 fat_num количество копий FAT
(+9) 2 max_dir максимальное число дескрипторов файлов в корневом каталоге (т.е. максимальное число файлов, которое может содержать корневой каталог на этом устройстве)
(+11) 2 data_sec номер первого сектора данных на диске (номер сектора, соответствующего кластеру номер 2)
(+13) 2 hi_clust максимальное количество кластеров (равно увеличенному на 1 количеству кластеров данных)
(+15) 1 fat_size количество секторов, занимаемых одной копией FAT
(+16) 1 reserv1 зарезервироано
(+17) 2 root_sec номер первого сектора корневого каталога
(+19) 4 drv_addr FAR-адрес заголовка драйвера, обслуживающего данное устройство
(+23) 1 media байт описания среды носителя данных
(+24) 1 acc_flag флаг доступа, 0 означает, что к устройству был доступ
(+25) 4 next адрес следующего блока DDCB, для последнего блока в поле смещения находится число FFFF
(+29) 2 reserv2 зарезервироано
(+31) 2 built число FFFF в этом поле означает, что блок DDCB был построен
Файл sysp.h содержит определение типа DDCB для MS-DOS версии 4.х и 5.0:

/* Блок управления устройством 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()

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

Приведем тексты программ для получения адресов первого и последующих блоков DDCB:

/** *.Name get_fddcb * *.Title Получить адрес первого DDCB * *.Descr Функция возвращает адрес первого блока DDCB * *.Params DDCB far *get_fddcb(CVT far *cvt) * * cvt - адрес векторной таблицы связи * *.Return Указатель на первый блок DDCB **/

#include <stdlib.h> #include <stdio.h> #include "sysp.h"

DDCB far *get_fddcb(CVT far *cvt) {

DDCB far * ddcb; ddcb = cvt->dev_cb; return(ddcb); }

/** *.Name get_nddcb * *.Title Получить адрес следующего DDCB * *.Descr Функция возвращает адрес следующего блока DDCB * или 0, если это последний блок в цепочке * *.Params DDCB far *get_nddcb(DDCB far *ddcb) * * ddcb - адрес предыдущего DDCB * *.Return Указатель на следующий блок DDCB * или 0, если это последний блок в цепочке **/

#include <dos.h> #include "sysp.h"

DDCB far *get_nddcb(DDCB far *ddcb) {

DDCB far *ddcb_n;

ddcb_n = ddcb->next; if(FP_OFF(ddcb_n) == 0xffff) return((DDCB far *)0); return(ddcb_n); }

С помощью приведенной ниже программы можно просмотреть содержимое всех блоков DDCB. Так как при большом количестве дисков выводится очень много информации, следует использовать средство переназначения стандартного устройства вывода DOS:

show_ddc > drives.lst

Эта программа проверена для версии MS/DOS 4.01.

#include <dos.h> #include <stdio.h> #include <stdlib.h> #include "sysp.h"

void main(void);

void main(void) { CVT far *cvt; DDCB far *ddcb;

printf("\nБлоки управления дисковыми устройствами (DDCB)" "\nCopyright (C)Frolov A., 1990\n" "\n");

cvt=get_mcvt(); ddcb=get_fddcb(cvt);

for(;;) { if(ddcb == (DDCB far *)0) break; printf("Адрес DDCB: %Fp\n" "Номер устройства: %d\n" "Дополнительный номер: %d\n" "Размер сектора: %d\n" "Размер кластера в секторах: %d\n" "База размера кластера: %d\n" "Зарезервировано секторов: %d\n" "Число копий FAT: %d\n" "Макс. файлов в корневом каталоге : %d\n" "Первый кластер данных: %d\n" "Всего кластеров: %d\n" "Размер FAT в секторах: %d\n" "Первый сектор корневого каталога: %d\n" "Поле reserv1: %01X\n" "Адрес драйвера: %Fp\n" "Байт описателя среды носителя: %01X\n" "Флаг доступа: %01X\n" "Адрес следующего DDCB: %Fp\n" "Поле reserv2: %04X\n" "Блок построен: %04X\n" "-------------------------------------\n\n", ddcb, ddcb->drv_num, ddcb->drv_numd, ddcb->sec_size, ddcb->clu_size, ddcb->clu_base, ddcb->boot_siz, ddcb->fat_num, ddcb->max_dir, ddcb->data_sec, ddcb->hi_clust, ddcb->fat_size, ddcb->root_sec, ddcb->reserv1, ddcb->drv_addr, ddcb->media, ddcb->acc_flag, ddcb->next, ddcb->reserv2, ddcb->built); ddcb=get_nddcb(ddcb); } exit(0); }



Приведенный выше способ получения доступа к блокам DDCB больше всего подходит для просмотра блоков управления всеми дисковыми устройствами. Если вам требуется получить DDCB для какого-нибудь конкретного устройства, можно воспользоваться недокументированной функцией 32H прерывания INT 21H (со всеми ограничениями, связанными с использованием недокументированных возможностей).

Функция 32H получает в регистре DL номер устройства (0 - текущий диск, 1 - А: и т.д.) и возвращает в регистровой паре DS:BX адрес соответствующего DDCB. Если номер устройства был задан неправильно, регистр AL после выполнения функции будет содержать значение FF.

Если требуется получить адрес DDCB флоппи-диска, необходимо установить диск в приемный карман дисковода.

Приведем текст программы, возвращающей указатель на DDCB диска с заданным номером:

/** *.Name get_ddcb * *.Title Получить адрес DDCB заданного диска * *.Descr Функция возвращает адрес блока управления * устройством DOS DDCB * *.Params DDCB far *get_ddcb(int device_number) * * device_number - номер диска, для которого * требуется получить DDCB * Номер задается так: * 0 - текущий диск, 1 - В и т.д. * *.Return Указатель на DDCB заданного диска **/

#include <dos.h> #include <stdio.h> #include "sysp.h"

DDCB far *get_ddcb(unsigned char device_number) {

union REGS inregs, outregs; struct SREGS segregs;

inregs.h.ah = 0x32; inregs.h.al = 0; inregs.h.dl = device_number; intdosx( &inregs, &outregs, &segregs ); if(outregs.h.al == 0xff) return(DDCB far *)0;

return((DDCB far*)FP_MAKE(segregs.ds,outregs.x.bx)); }

Программа, приведенная ниже, выводит адреса всех DDCB. Можете запустить ее (она есть на дискете, прилагающейся к книге) и посмотреть, что получится. Не забудьте вставить флоппи-диски во все дисководы.

#include <dos.h> #include <stdio.h> #include <stdlib.h> #include "sysp.h"

void main(void);

void main(void) { DDCB far *ddcb; unsigned char dr;

for(dr=1;;dr++) { ddcb=get_ddcb(dr); if(ddcb == (DDCB far *)0) break; printf("%Fp\n",ddcb); } exit(0); }


Содержание раздела