по теме лабораторной работы




Лабораторная работа № 17-18

 

«Получение навыков в работе с таблицей размещения файлов»

Цель работы: получение практических навыков в работе с таблицей размещения файлов.

Краткие теоретические и учебно-методические материалы

по теме лабораторной работы

В DOS имеются два совершенно независимых метода работы с файлами: метод Управляющих Блоков Файлов (FCB - File Control Block) и метод файловых дескрипторов (Handle - переводится также как файловые описатель, файловое число, файловый индекс).

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

Метод FCB использует так называемую Дисковую Передаточную Область (DTA - Disk Transfer Area). При загрузке программы эта область выделяется программе системой, но программист может организовать собственную DTA и сообщить системе ее адрес. Весь обмен с дисками ведется только через DTA - назначенную системой или установленную программистом. Это, однако, не требует обязательной пересылки данных между DTA и рабочими областями программы, так как программист может в любой момент переназначить адрес DTA на свою рабочую область.

Задания для лабораторной работы:

Определить номера всех кластеров диска, которые занимает заданный преподавателем файл в текущем каталоге.

 

#include <dos.h>

#include <string.h>

#include <stdlib.h>

#include <stdio.h>

#include <conio.h>

#include <ctype.h>

/*-------------------------------------------------------------*/

/* Типи и структуры данных */

#define byte unsigned char

#define word unsigned int

#define dword unsigned long

#define daddr struct DADDR

struct DADDR { /* физический дисковый адрес */

byte h;

word s, t, ts;

};

struct PART { /* структура элемента раздела */

byte Boot, Begin_Hd;

word Begin_SecTrk;

byte SysCode, End_Hd;

word End_SecTrk;

dword RelSec, Size;

};

struct MBR

{ /* стpуктуpа Главной Загрузочной Записи */

char LoadCode[0x1be];

struct PART rt[4];

word EndFlag;

};

struct BootRec

{ /* структура корневой записи */

byte jmp[3], ident[8];

word SectSize;

byte ClustSize;

word ResSect;

byte FatCnt;

word RootSize, TotSecs;

byte Media;

word FatSize, TrkSecs, HeadCnt;

word HidnSecL, HidnSecH;

dword LongTotSecs;

byte Drive, reserved1, DOS4_flag;

dword VolNum;

char VolLabel[11], FatForm[8];

};

struct Dir_Item

{ /* структура элемента директории */

char fname[11];

byte attr;

char reserved[10];

word time, date, cl;

dword size;

};

void Read_Mbr(void); /* Чтение MBR и поиск требуе-

мого раздела */

void Read_Boot(void); /* Чтение boot-сектора */

void Get_First(void); /* Определение абсолютного номе-

ра сектора начала логического

диска */

void Read_Fat(void); /* Чтение FAT */

void Read_13(void *mem); /* Чтение сектора с омогощью

прерывания 13 */

void Sect_to_Daddr(dword sect); /* Формирование физического дискового

адреса из # сектора */

dword Clust_to_Sect(word clust); /* Вычисление номера сектора

из номера кластера */

word Next_Clust(word clust); /* Выборка следующего кластера

из FAT */

char *Get_Name(char *s, char *d); /* Выделение следующего элемен-

та из строки-задания */

int Find_Name(); /* Поиск имени в каталоге */

void End_of_Job(int n

struct PART part; /* текущий элемент раздела */

byte buff1[512]; /* буфер MBR и boot */

struct MBR *mbr; /* указатель на таблицу разделов */

struct BootRec *boot; /* указатель на корневую запись */

byte buff2[512]; /* буфер каталога и текста */

struct Dir_Item *dir; /* указатель на часть каталога */

char *text; /* указатель на текстовий буфер */

byte *fat; /* указатель на FAT */

char job[81]; /* строка-задание */

char *jobptr; /* текущий указатель в job */

char cname[12]; /* текущее имя для поиска */

byte Fdisk; /* физический номер диска */

daddr caddr; /* текущий дисковый адрес */

dword sect; /* текущий номер сектора */

word clust; /* текущий номер кластера */

byte fat16; /* признак формату FAT */

dword fsize; /* размер файла */

int dirnum; /* номер элемента в каталоге */

dword FirstSect; /* абс.сектор начала */

byte rootdir=1; /* признак корневого каталога

или подкаталога (1/0) */

word lastsect; /* последний сектор при чтении */

byte fatalloc=0; /* признак выделения памяти */

/*-------------------------------------------------------------*/

main() {

int n,i;

textattr(14);

clrscr();

/* ввод имени файла */

cprintf(" Просмотр таблицы FAT. ");

cprintf("Укажите полное имя файла -->");

scanf("%s",job);

/* перевод в верхний регистр */

strupr(job);

/* проверка правильности идентификатора диска */

if ((!isalpha(job[0]))||(job[1]!=':')||(job[2]!='\\')) {

printf("%c%c%c -",job[0],job[1],job[2]);

End_of_Job(0);

}

textattr(10);

clrscr();

printf(" Лабораторная работа N17-18");

printf(" Дисковые структуры данных DOS.");

textattr(14);

cprintf("Файл %s в FAT занимает такие кластеры:\n",job);

jobptr=job+3;

if (job[0]>'A') {

/* для жесткого диска - физический номер и чтение MBR */

Fdisk=0x80;

Read_Mbr();

}

else /* для гибкого диска - физический номер */

Fdisk=job[0]-'A';

Read_Boot(); /* чтение boot-сектора */

Read_Fat(); /* чтение FAT */

dir=(struct Dir_Item *)buff2;

do { /* рух по каталогам */

if (!rootdir) clust=dir[dirnum].cl; /* начальный кластер */

/* выделение следующего элемента из строки-задания */

jobptr=Get_Name(jobptr,cname);

do { /* пока не дойдем до последнего кластера */

if (rootdir) { /* корневой каталог */

/* нач.сектор корневого кат. и количество секторов */

sect=boot->ResSect+boot->FatSize*boot->FatCnt;

lastsect=boot->RootSize*32/boot->SectSize+sect;

}

else { /* подкаталог */

sect=Clust_to_Sect(clust);

lastsect=boot->ClustSize+sect;

}

/* посекторное чтение всего корневого каталога

или одного кластера подкаталога */

for (; sect<lastsect; sect++) {

Sect_to_Daddr(sect);

Read_13(dir);

/* поиск имени в прочитанном секторе */

if ((dirnum=Find_Name())>=0) goto FIND;

}

/* до последнего кластера подкаталога */

}

while (clust=Next_Clust(clust));

/* весь каталог просмотрен, а имя не найдено - ошибка */

printf("%s -",cname);

if (jobptr==NULL) End_of_Job(4);

else End_of_Job(5);

 

FIND: /* имя найдено */

rootdir=0;

}

while (jobptr!=NULL);

/* найдено имя файла */

/* из каталога получеем 1-й кластер */

clust=dir[dirnum].cl;

textattr(7);

gotoxy(10,4);

cprintf("Нажимайте любую клавишу ");

cprintf(" пока не появится <КОНЕЦ ФАЙЛА>.");

textattr(12);

gotoxy(1,5);

cprintf("-<НАЧАЛО ФАЙЛА>");

gotoxy(1,6);

cprintf("L->");

i=0;

do {

i++;

if((i%10)==0) getch();

textattr(14+16);

cprintf("%4x",clust);

textattr(2);

cprintf("--->");

}

while (clust=Next_Clust(clust));

textattr(12);

cprintf("<КОНЕЦ ФАЙЛА>\n");

gotoxy(1,wherey());

textattr(15+3*16);

cprintf("Количество кластеров в файле: %u ",i);

End_of_Job(7);

}

/*-------------------------------------------------------------*/

/* Чтение MBR и поиск нужного раздела */

void Read_Mbr(void) {

int i;

char ndrive;

word *EndList;

caddr.h=0;

caddr.ts=1;

ndrive='C';

mbr=(struct MBR *)buff1;

 

NEXT: Read_13(buff1);

for (EndList=(word *)&mbr->rt[(i=0)];

(*EndList!=0xaa55)&&(mbr->rt[i].Size>0L);

EndList=(word *)&mbr->rt[++i]) {

if (mbr->rt[i].SysCode==5) {

caddr.h=mbr->rt[i].Begin_Hd;

caddr.ts=mbr->rt[i].Begin_SecTrk;

goto NEXT;

}

if (ndrive==job[0]) {

movmem(&mbr->rt[i],&part,sizeof(struct PART));

return;

}

else ndrive++;

}

/* требуемый раздел не найден */

printf("%c: -",job[0]);

End_of_Job(1);

}

/*-------------------------------------------------------------*/

/* Чтение boot-сектора */

void Read_Boot(void) {

if (Fdisk<0x80) {

caddr.h=0;

caddr.ts=1;

}

else {

caddr.h=part.Begin_Hd;

caddr.ts=part.Begin_SecTrk;

}

Read_13(buff1);

boot=(struct BootRec *)buff1;

Get_First();

}

/*-------------------------------------------------------------*/

/* Чтение FAT */

void Read_Fat(void) {

dword s, ls;

byte *f;

fat=(byte *)malloc(boot->FatSize*boot->SectSize);

if (fat==NULL) {

printf("Размещение FAT -");

End_of_Job(3);

}

fatalloc=1;

s=boot->ResSect;

ls=s+boot->FatSize;

for (f=fat; s<ls; s++) {

Sect_to_Daddr(s);

Read_13(f);

f+=boot->SectSize;

}

/* установление формата FAT */

if (Fdisk>=0x80)

if (part.SysCode==1) fat16=0;

else fat16=1;

else fat16=0;

}

/*-------------------------------------------------------------*/

/* Чтение сектора при помощи прерывания 13 */

void Read_13(void *mem) {

/* mem - адреса в ОП */

union REGS rr;

struct SREGS sr;

rr.h.ah=2;

rr.h.al=1;

rr.h.dl=Fdisk;

rr.h.dh=caddr.h;

rr.x.cx=caddr.ts;

sr.es=FP_SEG(mem);

rr.x.bx=FP_OFF(mem);

int86x(0x13,&rr,&rr,&sr);

/* Проверка ошибок чтения */

if (rr.x.cflag&1) {

printf("%u -",rr.h.ah);

End_of_Job(2);

}

}

/*-------------------------------------------------------------*/

/* Определение абс.номера сектора начала лог.диска */

void Get_First(void) {

word s, t;

if (Fdisk<0x80) FirstSect=0;

else {

/* формирование # сектора из физич. дискового адреса */

t=(part.Begin_SecTrk>>8)|((part.Begin_SecTrk<<2)&0x300);

s=part.Begin_SecTrk&0x3f;

FirstSect=(((dword)t*boot->HeadCnt)+part.Begin_Hd)*

boot->TrkSecs+s-1;

}

}

/*-------------------------------------------------------------*/

/* Формирование физического дискового адреса из # сектора */

void Sect_to_Daddr(dword sect) {

/* sect - номер сектора, caddr - адрес на диске */

dword s;

if (Fdisk>=0x80) sect+=FirstSect;

caddr.s=sect%boot->TrkSecs+1;

s=sect/boot->TrkSecs;

caddr.h=s%boot->HeadCnt;

caddr.t=s/boot->HeadCnt;

caddr.ts=(caddr.t<<8)|caddr.s|((caddr.t&0x300)>>2);

}

/*-------------------------------------------------------------*/

/* Вычисление номера сектора из номера кластера */

dword Clust_to_Sect(word clust) {

/* clust - номер кластера, возвращает номер сектора */

dword ds, s;

ds=boot->ResSect+boot->FatSize*boot->FatCnt+

boot->RootSize*32/boot->SectSize;

s=ds+(clust-2)*boot->ClustSize;

return(s);

}

/*-------------------------------------------------------------*/

/* Выборка следующего кластера из FAT */

word Next_Clust(word clust) {

/* clust - номер кластера, возвращает номер следующего кластера

или 0 - если следующего нет */

word m, s;

if (rootdir) return(0);

if (!fat16) {

m=(clust*3)/2;

s=*(word *)(fat+m);

if(clust%2) /* нечетный элемент */

s>>=4;

else /* четный элемент */

s=s&0x0fff;

if (s>0x0fef) return(0);

else return(s);

}

else {

m=clust*2;

s=*(word *)(fat+m);

if (s>0xffef) return(0);

else return(s);

}

}

/*-------------------------------------------------------------*/

/* Выделение следующего элемента из строки-задания */

char *Get_Name(char *s, char *d) {

/* s - строка задания, d - выделенный элемент, возвращает

указатель на новое начало строки задания. */

char *p,*r;

int i;

for(i=0;i<11;d[i++]=' ');

d[11]='\0';

if ((p=strchr(s,'\\'))==NULL) {

/* последний элемент строки - имя файла */

/* перезапись имени */

for(r=s,i=0; (i<8)&&*r&&(*r!='.'); i++,r++) *(d+i)=*r;

/* перезапись расширения */

if (*r) for(i=0,r++; (i<3)&&*r; i++,r++) *(d+8+i)=*r;

return(NULL);

}

else {

/* следующий элемент - имя подкаталога */

*p='\0';

for(r=s,i=0; (i<11)&&*r; i++,r++) *(d+i)=*r;

return(p+1);

}

}

/*-------------------------------------------------------------*/

/* Поиск имени в каталоге */

int Find_Name() {

int j;

/* cname - найденное имя; возвращает индекс найденного

элемента в массиве dir или (-1) */

for (j=0; j<boot->SectSize/sizeof(struct Dir_Item); j++) {

if (dir[j].fname[0]=='\0') {

/* конец использованных элементов каталога */

printf("%s -",cname);

if (jobptr==NULL) End_of_Job(4);

else End_of_Job(5);

}

if ((byte)dir[j].fname[0]!=0xe5) {

if (memcmp(dir[j].fname,cname,11)==0) {

/* если iм`я збiгатся, то:

- при поиске файла элемент не должен иметь атрибутов

"подкаталог" или "метка тома",

- при поиске подкаталога элемент должен иметь атрибут

"подкаталог" */

if (jobptr==NULL)

if (!(dir[j].attr&0x18)) return(j);

else

if (dir[j].attr&0x10) return(j);

}

}

}

return(-1);

}

/*-------------------------------------------------------------*/

/* Завершение (при n=0-5 - аварийное) */

void End_of_Job(int n) {

/* n - номер сообщения */

static char *msg[] = {

"неправильный идентификатор диска",

"логический диск отсутствует",

"ошибка чтения",

"нехватка памяти",

"подкаталог не найден",

"файл не найден",

"непредусмотренный конец файла",

"" };

/* освобождение памяти */

if (fatalloc) free(fat);

/* выдача сообщения */

textattr(12+128);

cprintf(" %s\n",msg[n]);

gotoxy(28,wherey());

cprintf(" Нажмите любую клавишу...\n");

textattr(7);

getch();

/* завершение программы */

exit(0);

}

Тестирование: -<НАЧАЛО ФАЙЛА>

8L->2410--->2411--->2412--->2413--->2414--->2415--->2416--->2417-

-->2418--->2419--->241a--->241b--->241c--->241d--->241e--->241f-

-->2420--->2421--->2422--->2423--->2424--->2425--->2426--->2427-

-->2428--->2429--->242a--->242b--->242c--->242d--->242e--->242f-

-->2430--->2431--->2432--->2433--->2434--->2435--->2436--->2437-

-->2438--->2439--->243a--->243b--->243c--->243d--->243e--->243f-

-->2440--->2441--->2442--->2443--->2444--->2445--->2446--->2447-

-->2448--->2449--->244a--->244b--->244c--->244d--->244e--->244f-

-->2450--->2451--->2452--->2453--->2454--->2455--->2456--->2457-

-->2458--->2459--->245a--->245b--->245c--->245d--->245e--->245f-

-->2460--->2461--->2462--->2463--->2464--->2465--->2466--->2467-

-->2468--->2469--->246a--->246b--->246c--->246d--->246e--->246f-

-->2470--->2471--->2472--->2473--->2474--->2475--->2476--->2477-

-->2478--->2479--->247a--->247b--->247c--->247d--->247e--->247f-

-->2480--->2481--->2482--->2483--->2484--->2485--->2486--->2487-

-->2488--->2489--->248a--->248b--->248c--->248d--->248e--->248f-

-->2490--->2491--->2492--->2493--->2494--->2495--->2496--->2497-

-->2498--->2499--->249a--->249b--->249c--->249d---><КОНЕЦ ФАЙЛА>

Количество кластеров в файле: 142

Ответы контрольные вопросы:

1. Опишите методы работы с файлами.

Ответ: В DOS имеются два совершенно независимых метода работы с файлами: метод Управляющих Блоков Файлов (FCB - File Control Block) и метод файловых дескрипторов (Handle - переводится также как файловые описатель, файловое число, файловый индекс).

2. Перечислите и дайте характеристику функций метода дескриптора.

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

3. Что такое раздел?

Ответ: Раздел — это часть документа, форматирование которой никак не связано с форматированием остального документа

4. Что такое атрибуты каталога?

Ответ: Атрибут каталога – это место хранения имен файлов, сведений об их размерах, времени и даты создания или обновления.

5. Что такое библиотека? Основные характеристики и назначение.

Ответ: Наборы функций необходимых для создания программ и приложений.

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

 

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2017-12-29 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: