Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Лабораторная работа № 17-18.  «Получение навыков в работе с таблицей размещения файлов». Краткие теоретические и учебно-методические материалы




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

 

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

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

Образовательные результаты, заявленные во ФГОС третьего поколения:

Студент должен

уметь:

- осуществлять разработку кода программного модуля на современных языках программирования;

- создавать программу по разработанному алгоритму как отдельный модуль;

- выполнять отладку и тестирование программы на уровне модуля

знать:

- основные этапы разработки программного обеспечения;

- основные принципы технологии структурного и объектно-ориентированного программирования;

- основные принципы отладки итестирования программных продуктов.

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

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

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

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

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

Пример:

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

Программа состоит из главной функции main() и одиннадцати вспомогательных функций.

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 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;         /* количество секторов */

   };

Стpуктуpа Главной Загрузочной Записи:

struct MBR

  {

   char LoadCode[0x1be]; /* программа загрузки */

   struct PART rt[4]; /* 4 элемента разделов */

   word EndFlag;     /* подпись MBR       */

   };

Структура загрузочной записи логического диска:

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;       /* атрибут        */

byte reserved[10];

word time;       /* время          */

word date;       /* дата           */

word cl;         /* номер 1-го кластера */

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

};

Переменные, глобальные для всей программы:

part - текущий элемент раздела;

buff1[512] - буфер MBR и boot;

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

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

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

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

*text - указатель на текстовый буфер;

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

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

jobptr - текущий указатель в job;

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

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

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

sect - текущий номер сектора;

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

fat16 - признак формата FAT;

fsize - размер файла;

dirnum - номер элемента в каталоге;

FirstSect - абсолютный номер сектора начала;

rootdir=1 - признак корневого каталога или подкаталога (1/0);

lastsect - последний сектор при чтении;

fatalloc=0 - признак выделения памяти.

Функция main запрашивает имя файла, потом обрабатывает его и, если все нормально, то запускает вспомогательные функции необходимые для просмотра FAT заданного файла. Функция Read_Mbr выполняет выборку элемента таблицы разделов для заданного диска. Функция Read_Boot считывает boot-сектор логического диска, причем для гибкого диска адрес этого сектора назначается - 0, 0, 1, а для жесткого - выбирается из part. Функция Get_First определяет абсолютный номер начального сектора логического диска и сохраняет его переменной First_Sect. Это значение вычисляется из физического адреса начала, который берется из полей Begin_Hd, Begin_SecTrk элемента таблицы разделов. Функция Read_Fat считывает в память FAT целиком, адрес начала FAT на диске и ее размер определяются из ранее прочитанного boot-сектора.

Функция Read_13 читает один сектор с помощью прерывания BIOS. Функция Sect_to_Daddr преобразует номер логического сектора в физический адрес. Функция Clust_to_Sect преобразует номер кластера в номер сектора. Функция Next_Clust определяет номер следующего кластера, анализируя FAT. Для последнего кластера (и для корневого каталога) эта функция возвращает нулевое значение. Функция Get_Name предназначена для лексического разбора задания, она выделяет из задания очередное слово и переназначает jobptr. Пустое (NULL) значение jobptr - свидетельство об исчерпании задания. Функция Find_Name выполняет поиск имени в каталоге. Здесь cname - требуемое имя, функция возвращает индекс найденного элемента в массиве dir или (-1). Функция End_of_Job выполняет выдачу на экран различных сообщений при ошибках или при завершении программы.

/* Подключение стандартных заголовков */

#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);      /* Завершение (при n=0-5 -

                                аварийное)           */

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

/* Переменнi */

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);

}

В процессе работы программы на экран выводится информация наподобие следующей:

Файл D: \TC\TC. EXE в FAT занимает такие кластеры:

Нажимайте любую клавишу пока не появится < КОНЕЦ ФАЙЛА>.

-< НАЧАЛО ФАЙЛА>

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. Опишите методы работы с файлами.

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

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

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

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

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...