Данному образовательному сайту пришлось несколько раз менять свое имя. С 2022 года доступ к нему обеспечивается по URL
emc.orgfree.com

emc.km.ru (2001-2007) ==> educomp.org.ru (2007-2011) ==> educomp.runnet.ru (2011-2021) ==> emc.orgfree.com (2022-...)
Более подробно об истории сайта можно прочитать здесь.


Учебные модели компьютера



Модели (software):

"Е14" (parallel !!!)
"S9PU" (parallel)

Модели (hardware):






Награды сайта
Награды сайта 2005

Процедуры и функции модуля Level3 – доступ к файлам (и к диску в целом)

INTERFACE
USES common, level1, level2;
PROCEDURE formClusterMap; {сформировать карту кластеров}
PROCEDURE putCatRec(n:INTEGER;s:mySector); {сохранить запись каталога об одном файле}
PROCEDURE writeMyFile(fn:STRING;mf:myFile); {записать файл}
PROCEDURE writeVirtualDisk(fn:STRING); {сохранить образ виртуального диска}
PROCEDURE readVirtualDisk(fn:STRING); {прочитать образ виртуального диска}
FUNCTION  readMyFile(fn:STRING):myFile; {прочитать файл}
FUNCTION  getCatRec(n:INTEGER):mySector; {прочитать запись каталога}
TYPE sName=STRING[cat_nam];
FUNCTION  getCatName(n:INTEGER):sName;  {извлечь из записи имя файла}
FUNCTION  getCatLen(n:INTEGER):INTEGER; {извлечь длину}
FUNCTION  getCatCluster(n,k:INTEGER):INTEGER; {извлечь номер кластера}
FUNCTION  fileID(fn:STRING;print:BOOLEAN):INTEGER;
{определить идентификатор (номер) файла с заданным именем}

Работа с каталогом

Функция GETCATREC

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

извлечь элемент массива по номеру

Уровень сложности

низкий

Модуль

Level3

Входные параметры

n: INTEGER – номер файла (file ID)

Выходные параметры

нет (только результат функции)

Тип результата

mySector

Вызываемые процедуры (функции)

нет

Глобальные переменные и константы

массив sectors

Действия

по номеру файла прочитать запись каталога для него

Проверки

нет

Комментарии

по номеру файла формирует из массива sectors запись каталога

противоположна процедуре putCatRec

Примечание. В авторской версии имитатора одна запись каталога занимает ровно один сектор. Поэтому file ID просто совпадает с номером сектора и функция тривиальна. Но это не обязательное требование, так что в более сложных системах могут потребоваться более сложные действия, а значит, выделение специальной функции оправдано.

Функция GETCATNAME

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

извлечь подстроку из элемента текстового массива

Уровень сложности

низкий

Модуль

Level3

Входные параметры

n: INTEGER – номер файла (file ID)

Выходные параметры

нет (только результат функции)

Тип результата

sName (в авторском варианте фактически STRING[8])

Вызываемые процедуры (функции)

getCatRec

Глобальные переменные и константы

нет

Действия

по номеру файла из записи каталога для него извлечь имя файла

Проверки

нет

Комментарии

по номеру файла из полной записи каталога вырезает только имя

Функция GETCATLEN

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

извлечь подстроку из элемента текстового массива и преобразовать в число

Уровень сложности

средний

Модуль

Level3

Входные параметры

n: INTEGER – номер файла (file ID)

Выходные параметры

нет (только результат функции)

Тип результата

INTEGER

Вызываемые процедуры (функции)

getCatRec

Глобальные переменные и константы

нет

Действия

по номеру файла из записи каталога для него извлечь длину файла и преобразовать в число

Проверки

выделенные символы должны образовывать число

Комментарии

по номеру файла из полной записи каталога вырезает только два символа, соответствующих длине файла; с помощью VAL они преобразуются в число, причем в случае ошибки выдается результат –1 и выводится сообщение

Функция GETCATCLUSTER

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

извлечь подстроку из элемента текстового массива и преобразовать в число

Уровень сложности

средний

Модуль

Level3

Входные параметры

n: INTEGER – номер файла (file ID); k: INTEGER – номер кластера в файле (от 1 до fs_ml)

Выходные параметры

нет (только результат функции)

Тип результата

INTEGER

Вызываемые процедуры (функции)

getCatRec

Глобальные переменные и константы

константа cat_cl0

Действия

по номеру файла из записи каталога для него извлечь номер нужного кластера и преобразовать в число

Проверки

выделенные символы должны образовывать число

Комментарии

по номеру файла из полной записи каталога вырезает только два символа, соответствующих номеру кластера; с помощью VAL они преобразуются в число, причем в случае ошибки выдается результат –1

Примечание. Очень важно учитывать возможность ошибки, поскольку в файле может быть неполное количество кластеров – тогда GETCATCLUSTER выдаст –1. Процедуры более высокого уровня должны производить сравнение с –1.

Процедура PUTCATREC

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

сохранить запись каталога в нужный сектор

Уровень сложности

средний

Модуль

Level3

Входные параметры

n: integer – номер файла (file ID); s:mySector – содержимое записи каталога

Выходные параметры

нет

Вызываемые процедуры (функции)

нет

Глобальные переменные и константы

массив sectors

Действия

сохраняет указанное содержимое в область каталога виртуального диска

Проверки

нет

Комментарии

по номеру файла запись заносится в нужный сектор каталога

противоположна функции getCatRec

Функция FILEID

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

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

Уровень сложности

средний

Модуль

Level3

Входные параметры

fn: STRING – имя файла; print: BOOLEAN – выводить ли сообщение об отсутствии файла

Выходные параметры

нет (только результат функции)

Тип результата

INTEGER

Вызываемые процедуры (функции)

getCatName

Глобальные переменные и константы

константа fs_mnf

Действия

найти в каталоге файл с заданным именем и выдать его номер – fileID; при отсутствии файла результат –1

Проверки

нет

Комментарии

просматриваются все записи каталога: с помощью функции getCatName из них выделяется имя файла и сравнивается с заданным; при совпадении в качестве ответа выдается номер записи в каталоге, а в случае отсутствия требуемого имени –1 (при print = true дополнительно выводится текст File <имя> not found)

Примечание. Данная функция полезна еще и тем, что позволяет проверить, есть ли указанное имя в каталоге (если нет, то результат равен –1). Например, при переименовании файла его “старое” имя должно быть найдено в каталоге, а “новое”, напротив, должно отсутствовать.

Работа с картой кластеров

Карта кластеров – это массив их занятости: каждому кластеру соответствует элемент массива, равный 0, если кластер свободен, и 1 – если он распределен в файл. Карта требуется при записи на диск нового файла (для чтения достаточно каталога).

Процедура FORMCLUSTERMAP

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

сформировать числовой массив по определенным правилам

Уровень сложности

высокий

Модуль

Level3

Входные параметры

нет

Выходные параметры

нет

Вызываемые процедуры (функции)

getCatName, getCatCluster

Глобальные переменные и константы

массив clusterMap; константы dsk_ns, fs_spc, fs_mnf, fs_ml, pusto

Действия

карта кластеров очищается; считываются записи каталога, для всех существующих файлов извлекаются номера кластеров и в карте делаются отметки о занятости

Проверки

стертые файлы при составлении карты игнорируются

Комментарии

для проверки стерт ли файл первый символ имени сравнивается с pusto; перебираются все файлы и в каждом из них все кластеры

Примечание. Данная функция вызывается не только при инициализации виртуального диска, но и после удаления файлов, что автоматически “освобождает” удаленные кластеры.

Функция NEXTCLUSTER

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

найти в массиве первое нулевое значение

Уровень сложности

средний

Модуль

Level3

Входные параметры

нет

Выходные параметры

нет (только результат функции)

Тип результата

INTEGER

Вызываемые процедуры (функции)

нет

Глобальные переменные и константы

массив clusterMap; константы dsk_ns, fs_spc

Действия

находит в карте кластеров первый не занятый элемент и возвращает его номер (–1 при отсутствии)

Проверки

если массив пройден, а элемента нет – диск заполнен

Комментарии

ищется первый нулевой элемент в карте кластеров; если индекс выходит за пределы, значит такого элемента нет; в найденный элемент заносится 1, т.е. выбранный кластер “занимается”; количество кластеров определяется как число секторов деленное на количество секторов в кластере

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

Работа с файлами

Функция READMYFILE

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

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

Уровень сложности

средний

Модуль

Level3

Входные параметры

fn: STRING – имя файла

Выходные параметры

нет (только результат функции)

Тип результата

myFile

Вызываемые процедуры (функции)

fileID, getCatCluster, getCatLen, getCluster (Level2)

Глобальные переменные и константы

массив clusterMap; константы dsk_ns, fs_spc

Действия

если файл существует, циклически читает все входящие в него кластеры, “суммируя” их содержимое в общую строку; отбрасывает лишние символы последнего кластера, используя сведения о длине

Проверки

существование файла на виртуальном диске с помощью fileID

Комментарии

если файл найден, из каталога извлекаются сведения о его кластерах (getCatCluster) и они читаются; полученная в результате строка укорачивается в соответствии с длиной файла в каталоге

противоположна процедуре writeMyFile

Процедура WRITEMYFILE

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

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

Уровень сложности

высокий

Модуль

Level3

Входные параметры

fn: STRING – имя файла; mf: myFile – его содержимое

Выходные параметры

нет

Вызываемые процедуры (функции)

nextCluster, putCatRec, putCluster (Level2), addToCat (локальная, добавляет к записи для каталога 2 цифры)

Глобальные переменные и константы

константы dsk_bps, fs_spc, pusto

Действия

имя файла, если необходимо, дополняется пробелами или “урезается”; к имени добавляется длина файла в виде двух цифр; затем файл mf разбивается на кластеры, которые сохраняются на диск по номерам, находимым nextCluster, причем номера фиксируются в записи для каталога; находится неиспользуемое место в каталоге и, если удается, сохраняется сформированная запись

Проверки

длина имя не должна превышать максимального; количество файлов не может превысить заданного

Комментарии

fn приводится к стандартной длине; по мере записи формируется строка с записью для каталога, которая в конце сохраняется (при этом используется addToCat, которая переводит число в 2 символа, причем для значений меньше 10 добавляет слева 0); для разбивки на кластеры от mf “отрезается” слева количество байт в кластере, причем последний (неполный) дополняется символами pusto; при поиске свободного места в каталоге анализируется первый символ имени (< >pusto)

противоположна функции readMyFile

Работа с диском

Процедура READVIRTUALDISK

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

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

Уровень сложности

низкий

Модуль

Level3

Входные параметры

fn: STRING – имя файла MS-DOS

Выходные параметры

нет

Вызываемые процедуры (функции)

formClusterMap, fromDisk (Level1)

Глобальные переменные и константы

нет

Действия

вызвать процедуры считывания содержимого виртуального диска и формирования по нему карты кластеров

Проверки

для простоты нет, хотя корректность имени fn можно было бы проанализировать

Комментарии

противоположна процедуре writeVirtualDisk

Процедура WRITEVIRTUALDISK

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

используя имеющуюся в Level1 процедуру, организовать запись содержимого виртуального диска на винчестер

Уровень сложности

низкий

Модуль

Level3

Входные параметры

fn: STRING – имя файла MS-DOS

Выходные параметры

нет

Вызываемые процедуры (функции)

toDisk (Level1)

Глобальные переменные и константы

нет

Действия

вызвать процедуру записи содержимого виртуального диска

Проверки

для простоты нет, хотя корректность имени fn можно было бы проанализировать

Комментарии

фактически процедура служит “переходником” с Level3 на Level1 (в противном случае с Level4 потребовалось бы обращение на Level1!)

противоположна процедуре readVirtualDisk

Текст программы

UNIT level3; {Автор Е.А.Еремин. Пермь, 2004} {доступ к файлам} INTERFACE USES common, level1, level2; PROCEDURE formClusterMap; {сформировать карту кластеров} PROCEDURE putCatRec(n:INTEGER;s:mySector); {сохранить запись каталога об одном файле} PROCEDURE writeMyFile(fn:STRING;mf:myFile); {записать файл} PROCEDURE writeVirtualDisk(fn:STRING); {сохранить образ виртуального диска} PROCEDURE readVirtualDisk(fn:STRING); {прочитать образ виртуального диска} FUNCTION readMyFile(fn:STRING):myFile; {прочитать файл} FUNCTION getCatRec(n:INTEGER):mySector; {прочитать запись каталога} TYPE sName=STRING[cat_nam]; FUNCTION getCatName(n:INTEGER):sName; {извлечь из записи имя файла} FUNCTION getCatLen(n:INTEGER):INTEGER; {извлечь длину} FUNCTION getCatCluster(n,k:INTEGER):INTEGER; {извлечь номер кластера} FUNCTION fileID(fn:STRING;print:BOOLEAN):INTEGER; {определить идентификатор (номер) файла с заданным именем} IMPLEMENTATION (* DIRECTORY *) FUNCTION getCatRec(n:INTEGER):mySector; {прочитать запись каталога} BEGIN getCatRec:=sectors[n] END; FUNCTION getCatName(n:INTEGER):sName; {извлечь из записи имя файла} BEGIN getCatName:=COPY(getCatRec(n),1,cat_nam) END; FUNCTION getCatLen(n:INTEGER):INTEGER; {извлечь длину} VAR l,e:INTEGER; BEGIN getCatLen:=-1; val(COPY(getCatRec(n),cat_len,2),l,e);{преобразовать в число} IF e<>0 THEN WRITELN('incorrect file length') ELSE getCatLen:=l END; FUNCTION getCatCluster(n,k:INTEGER):INTEGER; {извлечь номер кластера} {n - file ID, k - cluster number in file (1..fs_ml)} VAR w:STRING; i,e:INTEGER; BEGIN VAL(COPY(getCatRec(n),cat_cl0+2*(k-1),2),i,e); IF e=0 THEN getCatCluster:=i ELSE getCatCluster:=-1 END; PROCEDURE putCatRec(n:INTEGER;s:mySector); {сохранить запись каталога об одном файле} BEGIN sectors[n]:=s END; FUNCTION fileID(fn:STRING;print:BOOLEAN):INTEGER; {определить идентификатор (номер) файла с заданным именем} VAR i:INTEGER; BEGIN fileID:=-1; i:=0; WHILE (i < fs_mnf) AND (fn<>getCatName(i)) DO i:=i+1; {ищем совпадение} IF i < fs_mnf THEN fileID:=i ELSE IF print THEN WRITELN('Файл "'+fn+'" не найден') END; (* CLUSTER MAP *) PROCEDURE formClusterMap; {сформировать карту кластеров} VAR i,k,w:INTEGER; s:STRING; BEGIN FOR i:=0 TO (dsk_ns DIV fs_spc)-1 DO clusterMap[i]:=0;{очистка} FOR i:=0 TO fs_mnf-1 DO {цикл по всем файлам} BEGIN s:=getCatName(i); IF s[1]<>pusto THEN {если файл есть} BEGIN FOR k:=1 TO fs_ml DO {цикл по кластерам} BEGIN w:=getCatCluster(i,k); IF w<>-1 THEN clusterMap[w]:=1; END END END; END; FUNCTION nextCluster:INTEGER; {анализирует карту кластеров: возвращает номер первого пустого кластера и помечает его как занятый} VAR i,l:INTEGER; BEGIN nextCluster:=-1; l:=dsk_ns DIV fs_spc;{число кластеров} i:=0; WHILE (i < l) AND (clusterMap[i]<>0) {ищем пустой кластер} DO i:=i+1; IF i < l THEN BEGIN nextCluster:=i; clusterMap[i]:=1 END ELSE WRITELN('Нет места на диске!') END; (* FILES *) FUNCTION readMyFile(fn:STRING):myFile; {прочитать файл} VAR id,j,w:INTEGER; mf:myFile; BEGIN id:=fileID(fn,true); IF id<0 THEN EXIT; mf:=''; FOR j:=1 TO fs_ml DO {читать все кластеры} BEGIN w:=getCatCluster(id,j); IF w<>-1 {кластер есть} THEN mf:=mf+getCluster(w); {добавить содержимое} END; w:=getCatLen(id); {file length} mf:=COPY(mf,1,w); readMyFile:=mf END; PROCEDURE writeMyFile(fn:STRING;mf:myFile); {записать файл} VAR cat,w:STRING; l,i,k,cs,n:INTEGER; PROCEDURE addToCat(i:integer); {добавляет к записи каталога двухразрядное десятичное целое} BEGIN STR(i,w); IF i<10 THEN w:='0'+w; cat:=cat+w; END; BEGIN WHILE LENGTH(fn) < cat_nam DO fn:=fn+' '; {дополнить пробелами короткое имя} IF LENGTH(fn)>cat_nam THEN fn:=COPY(fn,1,cat_nam); {если слишком длинное имя} cat:=fn; {начали формировать запись для каталога} l:=LENGTH(mf); {длина файла; считаем, что <100} addToCat(l); {добавить длину в кат. запись} cs:=dsk_bps*fs_spc; {размер кластера в байтах} k:=(l-1) div cs + 1;{количество кластеров в файле} FOR i:=1 TO k DO {запись кластеров} BEGIN n:=nextCluster; addToCat(n);{добавить в кат. запись} w:=COPY(mf,1,cs); {содержимое очередного кластера} DELETE(mf,1,cs); {убрать то, что запишем} WHILE LENGTH(w) < cs DO w:=w+pusto; {дополнить до cs} putCluster(n,w); {сохраняем в файл} END; WHILE LENGTH(cat) < dsk_bps DO cat:=cat+'-';{если кластеров мало} i:=0; {ищем пустое место в каталоге и заносим информацию о файле} WHILE (i < fs_mnf) AND (COPY(getCatRec(i),1,1)<>pusto) DO i:=i+1; IF i < fs_mnf THEN putCatRec(i,cat) ELSE WRITELN('Too many files!'); END; (* VIRTUAL DISK *) PROCEDURE readVirtualDisk(fn:STRING); {прочитать образ виртуального диска} BEGIN fromDisk(fn); formClusterMap; END; PROCEDURE writeVirtualDisk(fn:STRING); {сохранить образ виртуального диска} BEGIN toDisk(fn); END; END.


На главную страницу


Автор сайта - Евгений Александрович Еремин (Пермский государственный педагогический университет). e_eremin@yahoo.com


Free Web Hosting