5. ФАЙЛОВАЯ СИСТЕМА

5.1. Все может случиться,
или
Что нужно для работы

       — Здравствуйте, Александр Геннадьевич,— уже с порога поздоровался Алеша,— а что это сегодня так тихо и пусто?
       — Электричество отключили, вот они и не работают,— Александр Геннадьевич взглядом показал на машины. — Ну, мне-то всегда есть чем заняться — и профилактика, и ремонт, а тебе, к сожалению, ничем сегодня помочь не могу.
       — А я пойду домой,— говорит Алеша,— у меня там распечатки, полученные в прошлые разы, и я буду в них разбираться. Ведь для того, чтобы их понять, не всегда нужна ЭВМ. Иногда нужно просто удобное кресло и спокойная обстановка.
       Еще ближайшие десяток-другой лет у программистов не будет времени для безделья. В любой обстановке найдется дело.
       Придя домой, мы прежде всего решили подготовиться к работе. Программисты — те же писатели (а пока мы больше писатели, чем программисты), и им требуется найти удобный для себя распорядок и уютную окружающую обстановку. То что нельзя начинать работу, если в доме гости,— это, конечно, справедливо. И все же дома настолько спокойнее, чем в любом учреждении, что и дел делается во много раз больше. Может быть, вы предпочтете какие-нибудь другие условия. Не оставляйте поисков, пока не найдете для себя действительно удобной обстановки, а потом поймите, каким образом ее воспроизвести всякий раз, когда работаете.
       Мы с Алешей устроились на диване и запаслись достаточным количеством бумаги. Кроме того, нам необходимы те распечатки, которые мы получали раньше.
       — У меня есть распечатка каталога удаленных файлов,— сказал Алеша, доставая из стола папку с распечатками,— в одну колонку, да еще и в восьмеричной форме. Эту распечатку мы получали командой

    DIRECTORY/COLUMNS:1/OCTAL/PRINT/DELETED DX0:

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

    DIRECTORY/FULL/BLOCKS/OCTAL/COLUMNS:1/VOLUMEID/PRINT DX0:

       — Вот это уже то, что нам надо,— замечаю я,— но у нас там были еще дампы?
       — А дампов у нас много,— говорит Алеша, и начинает перечислять, во-первых — это распечатка начальных блоков монитора, которую мы получали командой

    DUMP/RAD50/END:6 SY:RT11SJ.SYS

       мы также делали распечатку драйвера DX.SYS командой

    DUMP/RAD50 SY:DX.SYS

       и, наконец, распечатки первых восьми блоков системного тома, так громко мы можем назвать нашу единственную дискету,— засмеялся Алеша.
       Так много распечаток, что пришлось поставить рядом еще два стула. Ведь хочется, чтобы распечатки можно было охватить одним взглядом. Теперь можно начинать работу.

 

5.2. Как устроен том?

       Мы так долго занимались глазами системы, что у нас зарябило в глазах. Каталоги во всех видах, таблицы чисел и символов, которые почему-то назвали дампом. И для чего все это нужно? Попробуем применить все это на практике.
       — Ну, с чего же мы начнем?— спрашиваю я Алешу.
       — Наверное, нужно плясать от печки,— пошутил Алеша, внимательно рассматривая распечатки,— я как раз и пытаюсь эту печку отыскать. Файловая система организована на томе, поэтому за основу я возьму распечатку дампа первых восьми блоков тома. Остальные распечатки будут нам помогать.
       Цифры нам пока мало о чем говорят, мы будем мыть золотой песок потихоньку, то есть искать то, что нам понятно.
       — Алеша, давай по порядку, по одному блоку. Например, что можно сказать о нулевом блоке?
       — Во-первых, в нулевом блоке мы видим только одну членораздельную запись в конце блока, которая начинается с адреса 750: — "?BOOT-U-", и второй ее кусочек: — "I/O ERROR".
       — Что о ней можно сказать?
       — Мне понятен только конец записи,— говорит Алеша,— ERROR означает ошибка, I/O — типовое сокращение от слов INPUT/OUTPUT (ввод/вывод), поэтому это сообщение означает "ошибка ввода/вывода".
       — Но тогда объяснение начала записи,— подсказываю я,— нужно искать в сообщениях об ошибках.
       — Это я понимаю,— говорит Алеша,— также понятно, что это фатальная ошибка, после которой система не может завершить работу. Совершенно непонятно слово BOOT, что в переводе с английского означает — "ботинок".
       — Тебе не понятно, что означает это жаргонное слово?— спрашиваю я.
       — И что означает,— говорит Алеша,— и особенно интересно откуда оно взялось.
       — Ну что же. Для начала нужно узнать значение слова BOOT. Для этого возьми пожалуйста "Словарь по компьютерам" под редакцией Фрэнка Гэлланда. Нашел?
       — Да,— говорит Алеша,— тут несколько слов, начинающихся с BOOT. Вот то, что нам нужно:

BOOT
       — (1) операция загрузки операционной системы и, возможно, другого системного программного обеспечения (с магнитной ленты или диска). Она бывает ложной для возникновения или, вернее, для востановления системы.


       — А также BOTTSTRAP,— переводит Алеша,— но это слово совсем непонятно. Ведь дословно оно означает "ремешок от ботинка". Тут, правда, есть разъяснение, из которого ясно, что это начальная загрузка программы.
       — Во-первых, обрати внимание, что Гэлланд различает BOOT — как общая загрузка операционной системы или ее восстановление — и BOOTSTRAP — как начальный ввод (first inputting) программы или операционной системы,— говорю я Алеше,— ведь именно слово "BOOTSTRAP" породило весь набор понятий, связанных с загрузкой. Ты правильно сказал, что "bootstrap" — это ремешек от ботинок. Делали раньше, а иногда и сейчас на заднике ботинка ремешок в виде петли, чтобы удобнее было его натягивать на ногу. А теперь вспомни, как барон Мюнхгаузен вытащил себя из болота?
       — За волосы,— отвечает Алеша,— он взял себя за волосы и вытащил из болота. Но ведь это сказка?
       — Конечно, сказка,— говорю я,— но в каждой сказке есть доля истины. Скажи, как можно загрузить в память ЭВМ программу, когда в ней еще нет ни одной программы?
       — А ведь и правда,— засмеялся Алеша,— это все равно, что поднять себя за волосы.
       — Или "поднять самого себя за ремешки от ботинок", как говорят англичане.
       — Теперь ясно,— говорит Алеша,— что нулевой блок содержит загрузчик ОС. А во-вторых, этот блок совпадает в основном с последним блоком драйвера DX.SYS. Значит, это не просто загрузчик системы, а загрузчик с устройства DX:. А так как он стоит в начале тома, то мы можем предположить, что он является начальным.
       — И на этом загрузчик кончается?— спрашиваю я.
       — Нет, есть и дальше,— говорит Алеша,— но тогда нужно перескочить через один блок, потому что блоки со 2-го по 5-й практически не отличаются от начальных блоков монитора и в них тоже встречается слово BOOT.
       — Тогда зафиксируй,— говорю я Алеше,— то, что мы уже узнали.
       — Конечно,— Алеша взял чистый лист бумаги и написал:

       — 1. Нулевой блок системного тома содержит начальный загрузчик системы, который копируется в него из последнего блока драйвера системного устройства.

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

?BOOT-W-Invalid or missing TT.SYS
       — неправильный или отсутствующий драйвер терминала
       Система работать будет, потому что драйвер системного терминала находится в резидентном мониторе, но при указании терминала, как устройства в спецификации файла, будет выдаваться сообщение, что такое устройство отсутствует.

?BOOT-W-SWAP.SYS not found
       — файл SWAP.SYS не найден
       В таком случае для нормальной работы системы необходимо записать на системный том файл SWAP.SYS либо командами управления системой выбрать такой режим, в котором этот файл не нужен. Эти команды мы узнаем позже.

?BOOT-W-Handler file not found
       — файл драйвера системного устройства не найден
       ОС RT-11 очень гибкая система, в ней возможно перерабатывать любые модули. В данном случае загрузчик предупреждает, что ввиду отсутствия драйвера системного устройства монитор должен сам уметь работать с этим устройством.

?BOOT-W-SWAP file too small
       — файл SWAP.SYS мал
       Для нормальной работы можно предпринять такие же действия как и в отсутствии файла SWAP.SYS. Однако если учесть, что SWAP.SYS является буфером, то достаточно просто увеличить его размер.

?BOOT-W-Error reading handler
       — ошибка чтения драйвера
       Это сообщение выдается при попытке прочитать драйвер устройства для включения его в систему, если при этом происходит ошибка аппаратуры или носителя. Если системный том плохой, то сообщение может выдаваться столько раз, сколько плохих драйверов записано на системном томе. С системой работать можно, если не пользоваться устройствами, драйверы которых не были прочитаны. В противном случае будет выдано сообщение об отсутствии данного устройства, несмотря на то что драйвер устройства (плохой) есть на системном томе. К сожалению, загрузчик не печатает имя плохого драйвера, но его можно узнать, проверив системный том на плохие блоки.

?BOOT-W-Monitor file not found
       — файл монитора не найден
       Загрузчик должен загрузить в память монитор, имя которого записано в конце пятого блока. Не найдя в каталоге системного тома этот файл, загрузчик не знает, что делать дальше.

?BOOT-W-Conflicting SYSGEN option
       — конфликт параметров генерации системы
       Это сообщение также следствие гибкости системы. При построении ОС RT-11 пользователь может указать некоторые параметры, в соответствии с которыми будут выбраны или изменены функции системы. Загрузчик монитора проверяет, соответствует ли набор параметров монитора такому же набору параметров у драйверов. В случае различия выдается это сообщение. Заметим, что некоторые драйверы, например SL.SYS, могут приспосабливаться к параметрам генерации системы. Для некоторых код набора параметров можно установить вручную. Так как у всех драйверов он хранится в ячейке с адресом 60, то, посмотрев этот код у драйвера системного устройства, можно записать такой же в нужный драйвер.
       А в конце пятого блока прямо указано, что это загрузчик монитора RT11SJ (BOTRT11SJ) с устройства DX:, и записано приветствие системы "RT-11SJ V05.00", которое мы видели при загрузке системы.
       Такое большое количество сообщений говорит о том, что перед нами основной загрузчик монитора, тем более что имя его указано.
       — А не проще было,— спрашивает Алеша,— просто загрузить монитор в память и передать ему управление?
       — Но по сообщениям видно,— отвечаю я,— что прежде, чем передать управление монитору, загрузчик проверяет аппаратуру и программы для того, чтобы он смог работать.
       — Значит,— выводит Алеша,— загрузчик проверяет, какие из устройств подключены в системе?
       — И только про драйверы этих устройств загрузчик сообщает монитору,— заканчиваю я,— но даже если устройство подключено, параметры генерации должны быть такими же, как у монитора.
       — Это нужно зафиксировать,— и Алеша, пропустив несколько строк от первой записи, написал:
       — 3. Со 2-го по 5-й блок идет загрузчик монитора, который кроме загрузки тестирует аппаратную и программую части системы и выполняет другие подготовительные операции, необходимые для работы монитора. Этот загрузчик переписывается из 1-4-го блоков файла монитора.
       Конечно, не вся информация лежала на блюдечке. Часть ее была привнесена извне. Но таким образом, по крупицам можно узнать многое. И кстати, в ОС CP/M под генерацией системы понимается именно запись монитора и загрузчика в начальные блоки тома, а не получение новой системы с заданными параметрами, как это понимается в RT-11.
       Теперь можно приняться и за первый блок. Наш том маленький и хороший, ошибок при работе с ним мы пока не замечали. А поэтому первый блок такой чистый — одни нули. И сначала посмотрим то, что лежит на блюдечке.
       Первое, что бросается в глаза, — это знакомые записи, которые мы видели при распечатке каталога тома.
       С адреса 730 двенадцать символов в коде ASCII показывают то, что в каталоге называется идентификатор тома — "RT11SJ V5.00".
       С адреса 744 двенадцать символов в коде ASCII показывают то, что в каталоге названо именем владельца — "АШАРИНА И.В.".
       И с адреса 760 также двенадцать символов в коде ASCII показывают нам то, что мы пока нигде не видели, но можем прямо сказать, что это идентификатор системы — название фирмы-разработчика "DEC" и название операционной системы "RT11A".
       И вроде все, что нам понятно?
       Нет, есть еще версия операционной системы в коде RADIX-50, которая инициировала (т.е. создавала вновь) файловую систему на томе "V05".
       Остались только два непонятных числа по адресу 722 и 724. Понятно, что весь первый блок тома служебный и содержит признаки, необходимые для работы с томом. Подумаем, что нам может потребоваться для этого. Первое — найти на томе файлы, записи о которых хранятся в каталоге. А где находится каталог? — Он начинается с 6-го блока. Это мы видим по дампу, и это же число записано по адресу 724. Его размер нам сообщила программа DIR — 1 сегмент, и это число мы видим по адресу 722.
       Зафиксируем и это:

       — 2. Первый блок содержит идентификаторы тома, владельца и системы, а также справочную информацию для файловой системы.

       Какие выводы можно сделать из полученной информации? Мы видим, что сообщение об ошибке выдает загрузчик. Загрузчиков два — первичный (начальный) в нулевом блоке, и вторичный (основной) — со 2-го по 5-й блок. Из сообщений загрузчиков мы определили, что загрузчик тестирует систему. Младшие версии RT-11 имели меньше тестов и различных проверок. Поэтому при загрузке разных версий системы на одной и той же системе получались неодинаковые результаты. Так, младшие версии могли загрузить монитор на частично неисправной аппаратуре и отказаться работать на исправной.
       Например, загрузчик V3.0 и младше проверял наличие оперативной памяти процессора только путем чтения. В результате, не мог обнаружить установленное ПЗУ и прекращал работу, не выдав никаких сообщений.
       До V4.0 не проверялись драйверы устройств, и они соответственно не включались в систему. Это должен был делать пользователь.
       Так как первичный загрузчик записывается из последнего блока драйвера системного устройства, то при выдаче сообщения ?BOOT-U-I/O ERROR первое, что необходимо сделать (при исправной аппаратуре и носителе), — это записать новый драйвер системного устройства и снова скопировать загрузчик.
       Однако может испортиться и вторичный загрузчик, и так как он переписывается из первых блоков монитора, то второй путь восстановления загрузчика — это заменить файл монитора и снова скопировать загрузчик.
       И самое обидное бывает, когда у тома, заполненного информацией, вдруг портится первый (системный) блок. В таких случаях программа DIR выдает об этом сообщение и отказывается работать. Сразу предупредим, что и в этом случае возможно спасти файлы, хотя и действовать придется вслепую. Но об этом потом. А сейчас разберемся с домовой книгой.

 

5.3. Заглянем в домовую книгу,
или
Структура каталога

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

       BLOCK NUMBER  00006
       000/ 000001 000000 000001 000000 000010
              A             A             H
       012/ 102000 075131 062000 075273 000032 000000 002654
            UD2    SWA    P      SYS      Z            6L
       030/ 102000 071677 142302 075273 000111 000000 006514
            UD2    RT1    1SJ    SYS     A3           BED
       046/ 102000 100040 000000 075273 000002 000000 006514
            UD2    TT            SYS      B           BED
       064/ 102000 016300 000000 075273 000003 000000 006514
            UD2    DX            SYS      C           BED
       102/ 102000 074240 000000 075273 000015 000000 006514
            UD2    SL            SYS      M           BED
       120/ 102000 046600 000000 075273 000002 000000 006514
            UD2    LP            SYS      B           BED
       136/ 102000 052400 000000 075273 000012 000000 006514
            UD2    MX            SYS      J           BED
       154/ 102000 054540 000000 075273 000002 000000 006514
            UD2    NL            SYS      B           BED
       172/ 102000 071070 000000 075273 000003 000000 006514
            UD2    RK            SYS      C           BED
       210/ 102000 052140 000000 075273 000011 000000 006514
            UD2    MT            SYS      I           BED
       226/ 102000 015600 000000 075273 000003 000000 006514
            UD2    DP            SYS      C           BED
       244/ 102000 045640 000000 075273 000010 000000 006514
            UD2    LD            SYS      H           BED
       262/ 002000 062570 000000 073376 000035 000000 004314
             YX    PIP           SAV      /           APL
       300/ 002000 016130 000000 073376 000055 000000 004314
             YX    DUP           SAV     AE           APL
       316/ 002000 015172 000000 073376 000023 000000 004314
             YX    DIR           SAV      S           APL
       334/ 002000 016125 062000 073376 000011 000000 004314
             YX    DUM    P      SAV      I           APL
       352/ 002000 016336 023364 015172 000002 000000 000000
             YX    DX0    FIL    DIR      B
       370/ 002000 016306 035045 015172 000002 000000 017656
             YX    DXF    ILE    DIR      B           EB0
       406/ 001000 007347 012170 015622 000342 000000 006156
             L2    BOO    CK     DPR     EZ           A9V
       424/ 004000 007347 012170 015622 000161 000000 006156
            AKH    BOO    CK     DPR     B3           A9V
       442/ 004000 026676 140700 015533 000160 000000 031655
            AKH    GL0    1      DOC     B2           HJ/
       460/ 004000 026676 140700 015533 000160 000000 031655
            AKH    GL0    1      DOC     B2           HJ/
       476/ 004000 016125 062000 073376 000335 000000 026715
            AKH    DUM    P      SAV     EU           GME
       514/ 004000 000000 000000 000000 000000 000000 000000
            AKH

       Теперь, сравнив полученную таблицу с каталогом, мы можем заметить, что во всех строках полученной нами таблицы (кроме первой) записана информация о файлах. Разберем строку по 16-ти разрядным словам.
       Нулевое слово содержит какой-то признак или сумму признаков. Так, записи с содержимым нулевого слова 102000 соответствуют файлам в каталоге с признаком "P". В то же время все записи о файлах, которые мы видим в распечатке каталога, содержат в нулевом блоке число 2000. Кроме того, мы видим записи о файлах, которые в распечатку каталога не попали. Эти записи содержат в нулевом слове число 1000 либо 4000. Будем надеяться, что в дальнейшем выясним, что есть что.
       Первое, второе и третье слова записи о файле, как видно невооруженным глазом, содержат имя и тип файла в коде RADIX-50. Но вот в следующем, четвертом слове содержится какое-то число. Если мы поищем эти числа в распечатке каталога, то увидим, что это размер файла. И наконец, пятое слово содержит нуль, а в шестом слове опять какая-то константа. Так как в распечатке каталога остался только один признак, который мы еще не связали с записью, — дата, то можно предположить, что шестое слово содержит дату.
       Итак, начнем разбираться с нулевым словом. Будем отмечать различие констант в нулевом слове и как это отражено в распечатке каталога.
       — Все записи о файлах, которые мы видим в распечатке каталога, имеют в нулевом слове константу 2000.
       — Все записи о файлах, у которых в распечатке каталога стоит символ "P", имеют в нулевом слове константу 102000, которую можно представить как сумму 100000+2000.
       — Запись, которая в распечатке каталога обозначается словом <UNUSED>, в дампе отражается как запись о файле BOOCK.DPR с размером, равным размеру неиспользуемой зоны, и константой 1000 в нулевом слове.
       — Просуммировав размеры файлов, перечисленных в дампе до первой записи с константой 4000, мы видим, что они занимают том полностью. Файлы, записи о которых начинаются с константы 4000, в распечатке каталога отсутствуют. Отсюда можно предположить, что константа 4000 соответствует концу каталога.
       Теперь проанализируем полученные факты. Для удобства работы разделим нулевое слово на два байта и подпишем у каждой константы предполагаемые признаки. Получилась интересная таблица.

   001000 ==> 002 000  - Неиспользуемый
   002000 ==> 004 000  - Постоянный
   004000 ==> 010 000  - Маркер конца каталога
   100000 ==> 200 000  - Защищенный

       Как видно, в данном слове используется только один байт, и так как признаки состояния возрастают монотонно и отсутствует еще один признак, о котором мы говорили, — "ВРЕМЕННЫЙ", то очевидно признаку "ВРЕМЕННЫЙ" должен соответствовать код 001 или 000400.
       Кроме того, когда мы распечатывали суммарную информацию о каталоге, говорилось о том, что наш каталог состоит из одного сегмента. Отсюда следует, что код 010 означает маркер конца сегмента, а не каталога.
       Теперь мы можем уточнить нашу таблицу признаков состояния файла, содержащихся в нулевом слове записи о файле в каталоге.

   000400 ==> 001 000  - Временный
   001000 ==> 002 000  - Неиспользуемый
   002000 ==> 004 000  - Постоянный
   004000 ==> 010 000  - Маркер конца сегмента
   100000 ==> 200 000  - Защищенный

       О временном файле стоит сказать особо. И здесь мы скажем "ВНИМАНИЕ!!!".
       Запись о временном файле в распечатке каталога мы можем никогда не увидеть, потому что состояние "ВРЕМЕННЫЙ" у файла появляется только во время работы какой-нибудь программы при проведении операции вывода информации в файл. Для пользователя это состояние возникает при аварийном завершении программы — это и сбой по питанию, сбой аппаратуры, ошибка в программе. При этом для пользователя важно сохранить хотя бы ту информацию, которая в файл уже записана. Для этого в системе есть специальная команда управления системой CLOSE (закрыть). Команда синтаксиса не имеет, и если набрать:

  +---------------
  !  .CLOSE<ВК>
  !  -
  !  .^
  !

то система закроет все открытые файлы, т.е. изменит признак "ВРЕМЕННЫЙ" на "ПОСТОЯННЫЙ".
       Однако если нам информация не нужна, то все равно необходимо привести систему в устойчивое состояние. Для этого мы должны освободить открытые файлы еще одной командой управления системой PURGE (освободить), которая также не имеет синтаксиса и действует на все открытые файлы. Она изменит у открытых файлов признак "ВРЕМЕННЫЙ" на "НЕИСПОЛЬЗУЕМЫЙ".
       А как же с оставшимися файлами, которые имеют признак 4000? Про них можно сказать, что система при очистке или инициализации нового каталога не стирает информацию о старых файлах, а записывает в нулевое слово первой записи о файле маркер конца сегмента. Об этом надо помнить, когда возникает необходимость восстановить случайно удаленную информацию.
       В записи о файле осталось еще одно слово, значение которого нам необходимо разгадать. Мы уже догадались, что оно содержит дату. Но хотелось бы узнать, в каком коде или в каком формате она записана. Для решения этой головоломки выпишем в отдельную таблицу коды из шестого слова записи о файле и соответствующие им даты их распечатки каталога так, как это показано ниже.

    002654  ==>  13-Jan-84
    006514  ==>  10-Mar-84
    004314  ==>  06-Feb-84
    017656  ==>  21-Jul-86
    006156  ==>  .........

       Ни в одном из известных нам кодов невозможно записать дату в одном слове. Единственно возможный способ состоит в том, чтобы каждый элемент даты закодировать отдельным числом в двоичной системе счисления и потом каким-то образом составить из этих чисел одно слово. Посмотрим, насколько это возможно.
       В месяце может быть 31 день. Для записи кода дня необходимо пятиразрядное двоичное число, так как из пяти двузначных индикаторов можно составить 32 комбинации.
       Год состоит из 12 месяцев, поэтому для представления месяца необходимо четырехразрядное двоичное число.
       А как же год? У нас из 16 разрядов числа осталось только семь, из которых можно составить 128 комбинаций. Поэтому весьма вероятно, что закодированы только последние две цифры года. А год указанный — 84!!!
       Дальнейшая наша работа будет мало чем отличаться от работы дешифровальщика. Для этого перепишем каждое число в двоичном коде, даты расставим по порядку, день и месяц запишем в двоичном коде и посмотрим, что из этого получиться.

           Дата     Код         Двоичный код        Месяц  День
        13-Jan-84  002654  0.000.010.110.101.100     0001  01101
        06-Feb-84  004314  0.000.100.011.001.100     0010  00110
        10-Mar-84  006514  0.000.110.101.001.100     0011  01010
        21-Jul-86  017656  0.001.111.110.101.110     0111  10101

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

       0.000.010.110.101.100
          00.01

как видим, это единственное место. Но не будем спешить радоваться. Для проверки проделаем такую же операцию с остальными строками. Но подставлять отображение месяца будем только в уже найденное место.

       0.000.010.110.101.100     Jan
          00.01
 
       0.000.100.011.001.100     Feb
          00.10
 
       0.000.110.101.001.100     Mar
          00.11
 
       0.001.111.110.101.110     Jul
          01.11

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

       0.000.010.110.101.100
               0.110.1          15 ==> 13.
 
       0.000.100.011.001.100
               0.011.0          06 ==> 06.
 
       0.000.110.101.001.100
               0.101.0          12 ==> 10.
 
       0.001.111.110.101.110
               1.110.1          25 ==> 21.

       Опять мы смогли выделить одноименные разряды во всех словах, которые соответствуют нашему представлению дня. Но тогда на представление года остается только пять разрядов, и, как мы видим, год закодирован следующим образом.

       Год 1984 ==> 01.100 = 14 = 12.
 
       Год 1986 ==> 01.110 = 16 = 14.

       Ничего похожего на какое-либо отображение года, за исключением того, что разница между кодом года и действительным значением года одинакова и равна 1972. Довольно странная цифра, если забыть о том, что разработка RT-11 была начата в 1972 году.
       Таким образом, мы можем свести в общую таблицу все, что мы узнали про дату.

           0.000.000.000.000.000
              ММ ММД ДДД ДГГ ГГГ
              /   \/     \/    \
              !   !!     !!    !
              !   !!     !!    +------\  разряды 0-4
              !   !!     !+-----------/  ГГГГГ = Год-1972
              !   !!     !
              !   !!     +------------\  разряды 5-9
              !   !+------------------/  день месяца
              !   !
              !   +-------------------\  разряды 10-13
              +-----------------------/  номер месяца

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

       BOOCK.DPR   226  03-Mar-86  286

       Действительно, так выглядит запись в каталоге удаленных файлов.
       Исследование остальных файлов, которые оставили свои следы в шестом блоке, мы предоставляем читателю в качестве упражнения.

 

5.4. А что же на обложке?
или
Заголовок сегмента каталога

       Прежде чем разгадывать первую запись в нашей таблице, посмотрим, как можно вычислить номер блока, с которого начинается какой-нибудь файл.
       В записи о файле только один атрибут — размер файла. Но так как файлы неразрывны — сразу после конца одного файла следует начало другого,— то адресом файла может являться сумма размеров всех предшествующих в сегменте файлов. Необходимо только знать номер блока, с которого начинается самый первый файл, записанный в сегменте. Этот номер и записан в четвертом слове заголовка сегмента каталога.
       Нужно заметить, что неиспользуемая область на томе есть также файл с именем EMPTY.FIL, если том был только что инициализирован, или с именем файла пользователя, который был на этом месте.
       — А сколько записей о файлах может быть в сегменте?— интересуется Алеша.
       — Ну Алеша,— с досадой говорю я,— арифметику в школе ты уже проходил, а информацию о структуре каталога мы уже положили на блюдечко. Поэтому попробуй подсчитать сам.
       — Сегмент каталога состоит из 512. слов,— считает Алеша,— пять из которых занимает заголовок сегмента каталога. Запись о файле состоит из семи слов. Поэтому сегмент каталога может содержать:

               512. - 5
           N = -------- = 72. записи
                  7

       Однако маркер конца сегмента имеет такой же формат, как и запись о файле. Кроме того, сегмент должен заканчиваться записью о неиспользуемой области, хотя бы и с нулевым размером. Итого в одном сегменте можно описать 70 файлов.
       — А теперь, Алеша, посмотри на размер самого маленького устройства MX: — всего 432 свободных блока. Допустим, что у тебя файлы имеют размер один блок. Сколько файлов ты сможешь на него записать?
       — 432 файла,— не подумав, ответил Алеша.
       — И все записи влезут в один сегмент? Вот тебе домашнее задание (и для читателей тоже) — сколько сегментов каталога потребуется и сколько файлов размером в один блок можно записать на устройстве MX:.
       А теперь давай разбираться дальше. Допустим, что у нас есть 200 файлов по два блока, и взяли мы для каталога 3 сегмента. И записывали файлы подряд без промежутков. А потом понадобилось удалить файл размером 2 блока, записанный в первом сегменте, и вместо него записать два файла по одному блоку. А место для записи освободилось только одно. Вот и придумали разработчики фирмы DEC полностью заполнять только последний сегмент в этой цепочке. А предыдущие сегменты заполнять только наполовину, т.е. между каждым файлом можно расположить еще один файл, например неиспользуемый. И тогда во всех сегментах, кроме последнего, может быть не более 36 записей о постоянных файлах.
       Таким образом, при заполнении последнего сегмента открывается следующий, и половина записей из предыдущего переписывается в него. Значит, для 200 файлов потребуется не три, а пять сегментов. Единственный случай, когда все сегменты, имеющие записи, заполняются полностью, возникает при "сборке мусора", т.е. если мы попросим систему собрать все свободные области в одну, а заполненное файлами пространство сжать в начало тома.
       Отсюда следуют некоторые выводы.
       — Если мы хотим зарезервировать для каталога 10 сегментов, то должны сообщить об этом системе. Для этого служит нулевое слово заголовка сегмента каталога, в который записывается число зарезервированных сегментов каталога.
       — А записи о файлах у нас находятся, например, только в пяти сегментах. Значит, необходимо, чтобы система не тратила время на просмотр пустых сегментов, нужно указать, сколько сегментов открыто для записи. Для этого служит второе слово заголовка сегмента. Однако число открытых сегментов имеет смысл записывать только в первом сегменте и там же корректировать его при открытии или освобождении очередного сегмента. Так это и делается.
       — А теперь представим, что в результате всякого рода перипетий сегмент номер 3 освободился, а потом открылся снова. Поэтому и записи о файлах расположились не так, как сами записи на устройстве. Связи между сегментами при этом можно изобразить так:

                                  +---------------------------+
                                  !                           V
    +-------+    +-------+    +-------+     +-------+     +-------+
    !сегмент!--->!сегмент!    !сегмент!<----!сегмент!     !сегмент!
    !   1   !    !   2   !    !   3   !     !   4   !     !   5   !
    +-------+    +-------+    +-------+     +-------+     +-------+
                     !                          ^
                     +--------------------------+

       И раз сегменты расположились не по порядку, то необходимо в каждом сегменте указать, какой сегмент просматривать следующим. Поэтому в первое слово заголовка сегмента каталога записывается номер следующего сегмента. В последнем используемом сегменте первое слово содержит нуль.
       — И последнее. Пользователь — человек привередливый и может захотеть поместить в запись о файле какие-нибудь свои признаки, и запись о файле может состоять не из семи слов, а из большего числа. Система, правда, не будет обрабатывать дополнительные слова, пользователь должен сам об этом позаботиться. Но сообщить файловой системе о количестве дополнительных слов в записи необходимо. И записывается оно в третье слово. Число дополнительных слов может быть определено при инициализации каталога. Соответственно число записей в сегменте каталога будет меньше.
       А теперь суммируем все, что у нас получилось.
       — Нулевое слово содержит число сегментов, отведенных под каталог. Число сегментов задается по умолчанию (разное для различных устройств, в зависимости от объема тома) или по указанию пользователя при инициализации каталога. В нашем случае оно равно 1.
       — Первое слово содержит номер следующего сегмента каталога. Это слово является связующим между логически смежными сегментами каталога. В последнем используемом сегменте первое слово содержит нуль.
       — Второе слово содержит счетчик сегментов, имеющих записи. При открытии нового сегмента счетчик корректируется только в первом сегменте. В последующих сегментах содержимое этого слова не изменяется и равно нулю.
       — Третье слово содержит число дополнительных слов в записи о файле в каталоге. Может задаваться пользователем при инициализации каталога.
       — В четвертом слове содержится номер блока, с которого начинаются файлы, описанные в данном сегменте. В нашем случае он равен 10 (8.), и, действительно, если мы посмотрим дамп 10 блока, мы увидим какой-то двоичный файл. Исходя из каталога — это SWAP.SYS.

 

5.5. Структура тома с произвольным доступом

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

ЗАГОЛОВОК ТОМА
       Заголовок тома располагается в нулевом блоке и начинается с кода 000240. В случае отсутствия этого кода аппаратный загрузчик будет пытаться прочитать этот том снова. В заголовке тома располагается первичный загрузчик, который знает где находится основной загрузчик системы и как работать со своим устройством. Вся его задача сводится к загрузке основного загрузчика системы. В RT-11 основной загрузчик располагается в блоках со 2-го по 5-й включительно. Если том не системный и загрузка, как операция, не определена, то в нулевом блоке вместо загрузчика располагается программа вывода на терминал сообщения: BOOT NO VOLUME — загрузчика нет на томе. Содержимое блоков 2-го 5-й в таком случае не определено.

ИДЕНТИФИКАТОР ТОМА
       Располагается в первом блоке и содержит: количество сегментов каталога; номер блока, с которого начинается каталог; версию системы в коде RADIX-50, которая инициализировала каталог; идентификатор тома и имя владельца, введенные оператором при инициализации каталога; название фирмы-разработчика и название операционной системы.

ОСНОВНОЙ ЗАГРУЗЧИК МОНИТОРА
       Располагается в блоках со 2-го по 5-й включительно и служит для первоначальной или повторной загрузки операционной системы.

КАТАЛОГ ТОМА
       Располагается с 6-го блока тома. Сегмент имеет размер 2 блока. Число сегментов, отведенных под каталог, указано в нулевом слове каждого сегмента.

       — Андрей Германович,— спрашивает Алеша,— мы только не сказали, на каком устройстве организовали том, структуру которого мы так долго разбирали.
       — Молодец, Алеша, что ты это заметил. Все разговоры о расположении каталога тома и файлов на томе нам удалось провести, не упоминая о том, на каком устройстве находится том. Таким образом, мы в общем случае можем сказать, что том с точки зрения файловой системы RT-11 есть некоторая область памяти, которая имеет стандартный для системы заголовок тома и каталог.
       — Значит,— говорит Алеша,— том можно организовать на любой памяти.
       — Да,— отвечаю я,— вот, например, если мы возьмем файл на устройстве с произвольным доступом и запишем каким-нибудь образом в его начало заголовок тома и каталог, то, наверное, можно написать программу, которая будет работать с нашим файлом как с томом. И в третьей версии RT-11 появились программы, позволяющие создавать такие файлы-тома и работать с ними. Появились драйверы UX, UY, UZ, которые работали с файлами различного размера — 280., 560. и 1100. соответственно. Естественно, что если мы создали устройство UZ: размером 1100. блоков, то можем на нем создать файл размером 560. блоков и объявить его устройством UY:, после чего работать с ним, как с самостоятельным устройством. Внутри устройства UY: мы можем, как в матрешке, также создать устройство UX:. Как все устройства в RT-11, рассматриваемые нами логические устройства-файлы могут иметь номер от 0 до 7.
       Но работать с фиксированными размерами таких файлов не всегда удобно. Поэтому в версии RT-11 V4.0 для устройств UX:, UY:, UZ: размеры файлов можно было определять любые.
       И наконец, в версии RT-11 V5.0 поиски истины достигли своего логического конца. Драйверы UX, UY, UZ, а также программы, работающие с этими устройствами, были исключены. Функции работы с логическими дисками (LOGICAL DISK ==> LD:), как они теперь были названы, — инициализация каталога, связывание имени файла с именем устройства и его номером, были внесены в программу DUP, а для работы с файлом в систему был включен драйвер LD.SYS.
       Таким образом, у нас есть теперь устройства LD: с номерами от 0 до 7, которые можно вкладывать друг в друга, как матрешку. Это оказалось очень удобным. Дополнительные расходы памяти на организацию каталога окупаются более быстрым обращением к нужному файлу, так как каталог теперь может быть короче.
       На рисунке это образно можно изобразить так.

                +--------------------+
                !X!P1.MAC!P2.MAC!    !
                +--------------------+
      +------------------------------+---------------------------+
      !X!PRG.MAC!    MACRO.DSK       !X!PG.MAC!PG.PAS!PG.TXT!    !
      +------------------------------+---------------------------+
  +--------------------------------------------------------------+
  !RKX!     WORKIN.DSK               !     SOURCE.DSK            !
  +--------------------------------------------------------------+

       Здесь символом !X! условно обозначен каталог. И тогда про данный том можно сказать следующее:
       — Том находится на устройстве RK: и содержит два больших файла — WORKIN.DSK и SOURCE.DSK.
       — Файл SOURCE.DSK в свою очередь содержит каталог и файлы PG.MAC, PG.PAS, PG.TXT.
       — Файл WORKIN.DSK также содержит каталог и файлы PRG.MAC и MACRO.DSK. А файл MACRO.DSK в свою очередь имеет каталог и файлы P1.MAC и P2.MAC.
       — Следовательно, для того, чтобы добраться до файла P2.MAC, необходимо установить в системе, например, следующие соотношения.

           LD0: ::== RK:WORKIN.DSK
 
           LD1: ::== LD0:MACRO.DSK

       После этого можно сказать (а значит, и работать с файлом), что файл P2.MAC находится на устройстве LD1:.
       Таким образом, каждый файл может быть связан или, как говорят, смонтирован на устройстве LD: с любым номером. Мы получили возможность проводить операции с группой файлов, считая их как один. Это особенно важно при работе с магнитной лентой и архивами.
       — Андрей Германович,— говорит Алеша,— мы говорили, что в СОТКЕ есть дополнительная память у процессора. Можем ли мы в ней организовать подобное устройство?
       — А почему бы и нет?— отвечаю я.
       И в RT-11 V5.0 появляется устройство VM: (Virtual Memory — виртуальная память) и соответствующий драйвер. Физически — это та же быстрая память процессора, и если выключить питание, то информация пропадает. Но логически — это устройство с произвольным доступом. Так как память у процессора одна, то номер устройства VM: игнорируется. Еще одно отличие от устройства LD: состоит в том, что устройство VM: может быть системным, т.е. в заголовок тома можно записать загрузчик монитора и загрузить систему с устройства VM:. Что этим достигается? Чрезвычайно высокая скорость работы!
       Если дополнительной памяти мало, как, например, у СОТКИ, то устройство VM: используется в основном как буферное для различным программ. Однако у таких ЭВМ, как СМ-1420, "Электроника-60.1", "Электроника-79", "Электроника-85", ДВК-3 и ДВК-4, объем памяти может достигать до 4М байт, и тогда на устройство VM: можно перенести всю операционную систему.

 

5.6. Как лиса сыр делила,
или
Дисциплина распределения памяти

       Тома, тома. Они могут быть большими и маленькими, содержать два файла и сотни файлов. И для работы всегда нужна свободная область на томе, куда будет записана информация очередного файла. А если свободных областей много и все они различного размера, в которую из них система определит файл? Это обстоятельство нас может беспокоить в двух случаях: хватит ли места для очередного файла и, что более важно, где искать информацию, если произошла какая-нибудь авария.
       Начнем с самого простого случая — мы знаем или можем предположить, какого размера будет выходной файл. Это бывает редко, но все же, как бы поступили мы, экономя память для дальнейших работ. Очевидно выбрали бы область, наименьшую из тех, в которые влезет наш будущий файл. Именно так и принято в RT-11. И когда мы знаем, какого размера будет выходной файл, или нам необходимо по каким-либо причинам, чтобы запись о файле указывала на определенной место, нужно сообщить системе этот размер, например, ключем /ALLOCATE.
       Более сложный случай — когда мы (и система тем более) не знаем размера выходного файла. Необходимо также учесть, что в общем случае могут быть одновременно открыты три (иногда и более) выходных файла. А так как файлы открываются по очереди — мы должны учесть и это.
       Первое, что приходит в голову, — выбирать всегда самую большую область. С одной стороны — надежно. Если файл можно записать на том, то он всегда влезет. Но если мы захотим открыть два файла, причем второй будет немного больше первого? В таком случае — второй файл может и не влезть, хотя его размер меньше самой большой свободной области.
       Будем благоразумны и позаботимся о завтрашнем дне. Будем всегда брать второй по величине файл. Но при этом мы попадем в другую крайность. У нас могут не влезть оба файла в крошечные свободные области при наличии огромной самой большой свободной области, которая никогда не будет использована.
       Разработчики RT-11 приняли остроумное решение. Не рассматривая самые маленькие свободные области, они делают выбор из самой большой и второй по размеру свободной области. Эта дисциплина распределения памяти (или алгоритм) преследует простую цель — обеспечить двум последовательно открытым файлам примерно одинаковые условия. Так как вариантов у нас немного, попробуем сами найти этот алгоритм.
       Вариант 1. Первая область много больше второй. Как можно поступить в этом случае? Очевидно разделить ее пополам и отдать первую половину первому файлу.
       Вариант 2. Первая по величине область примерно равна второй. Бывает и такое. Тогда первому файлу и отдадим первую по величине область, а второму — вторую.
       — Но, Андрей Германович,— возражает Алеша,— мы должны оперировать точными понятиями. Что означает "примерно равны"? Где критерий "примерно"?
       А критерий этого "примерно",— отвечаю я,— заложен в нашей цели.
       Разделим первую по величине область пополам и будем сравнивать эту половину со второй по величине областью. Если вторая по величине область больше половины наибольшей, то отдадим ее первому файлу. Если меньше, то первый файл получит половину наибольшей области. В любом случае для двух файлов разница в размерах не будет превышать половины самой большой свободной зоны.
       Все сказанное можно продемонстрировать на рисунках

           /+-------+-\
          ! I       I  \
          ! I       I   \
          ! I       I    \.. первый файл
          ! I  300  I    /
          ! I       I   /
          ! I       I  /
         /  +-------+--
     600 \  I       I  \
          ! I  150  I   \.. второй файл
          ! I       I   /
          ! +-------+--/
          ! I       I
          ! I  150  I                         +-------+
          ! I       I                         I  100  I
           \+-------+                         +-------+
          П Е Р В А Я                        В Т О Р А Я
        свободная зона                      свободная зона

 
 
 
            /+-------+--
           ! I       I  \
           ! I       I   \
           ! I       I    \
           ! I  300  I     \.. первый файл
           ! I       I     /
           ! I       I    /
           ! I       I   /
      600 /  +-------+---
          \  I       I
           ! I       I
           ! I       I
           ! I  300  I                        +-------+\
           ! I       I                        I       I \
           ! I       I                        I  200  I  \. второй
           ! I       I                        I       I /   файл
            \+-------+                        +-------+/

            П Е Р В А Я                      В Т О Р А Я
           свободная зона                    свободная  зона
 
 
 
            /+-------+--
           ! I       I  \
           ! I       I   \
           ! I       I    \
           ! I  300  I     \__ второй файл
           ! I       I     /
           ! I       I    /
           ! I       I   /                    +-------+\
      600 /  +-------+---                     I       I !
          \  I       I                        I       I !
           ! I       I                        I       I !
           ! I       I                        I  320  I  \ первый
           ! I  300  I                        I       I  / файл
           ! I       I                        I       I !
           ! I       I                        I       I !
           ! I       I                        I       I !
            \+-------+                        +-------+/
 
            П Е Р В А Я                      В Т О Р А Я
           свободная зона                    свободная  зона

       Однако, где в таком случае искать информацию (в какой половине) и каким образом. Очень просто. В случае какой-нибудь аварии, когда программа не успела установить признак "ПОСТОЯННЫЙ" выходным файлам, программа DIR на месте разделенной свободной области покажет две одинаковые по размеру (или отличающиеся на один блок) и следующие друг за другом. В первой из них (считая по порядку от начала тома) и будет находиться информация. Это следует и из рисунков, приведенных выше.
       При открытии файла прикладная программа дала ему имя и тип. Если вывести на дисплей каталог удаленных файлов, то мы увидим запись о файле с этим именем, и, соответственно, на его месте следует искать информацию.
       Осталось только восстановить запись в каталоге.

 

5.7. Для чего это нужно,
или
Восстановление доступа к информации

       Случай поиска информации, рассмотренный при определении дисциплины распределения памяти, позволяет восстановить доступ к информации, используя данные в каталоге тома. А как быть, если испорчен каталог тома и этих данных нет? Как узнать, где файл начинается и где кончается. А также какая информация находится в файле.
       Вот здесь нам и пригодится программа DUMP.
       Начнем с того, что разделим информацию — что относится к одному файлу, а что к другому. А для этого нужно примерно определить назначение файла, тип информации в нем и по ней уже определять границы файла. Посмотрим на те файлы, назначение которых нам известно. Причем нас будет в основном интересовать, как выглядит дамп начала и конца файла. Дамп любого файла отличается своим характерным ритмом в числах, отображающих информацию. По изменению этого ритма мы и будем определять начало и конец файла.
       Файл DXFILE.DIR мы создали сами с помощью программы DIR и говорили, что он текстовой. И в дампе этого файла мы действительно видим, что двоичные коды, преобразованные в символы ASCII, составляют текст, который нам показывала программа DIR. При этом текст начинается с начала нулевого блока файла. Последний же блок частично заполнен текстом, а оставшаяся часть заполнена нулями. Таким образом, если несколько текстовых файлов расположены друг за другом, то граница между ними легко различается по нулевым байтам в конце последнего блока предшествующего файла и осмысленным текстом с начала нулевого блока последующего файла. Остается только занести в каталог запись об этом файле.
       Но у нас имеются не только текстовые файлы. Например, как выглядят программы в файлах, имеющих тип .SAV. Допустим, как выглядит дамп программы DUMP? Если вы его не получили сами, то мы его приведем в приложении 3.
       Мы должны сразу отметить, что программа DUMP.SAV начинается с нулей и только третья строчка (в нашем дампе) с адреса 000040 заполнена какими-то числами. Часть чисел имеют значение только для системы и программистов, поэтому мы их рассматривать не будем. Нас интересуют два числа — адрес начала программы и адрес ее конца.
       Начало программы мы уже видели — это блок, начавшийся с нулей и с характерно заполненными 3 и 16 строчками.
       А конец программы должен быть заведомо дальше верхнего адреса программы, который искать нужно в ячейке по адресу 000050. В нашем случае это значение равно 7754 (восьмеричное). И размер файла при этом можно определить, округлив это число до ближайшего большего числа кратного 1000 и разделив на 1000 (восьмеричное).
       Таким образом, для восстановления записи о файле в каталоге имеется вся информация — начальный блок и размер файла.
       Попробуем убедиться в этом и посмотрим таким же образом дамп программы DUP.SAV. И все вроде бы хорошо — начальный блок нашли правильно и числа в общем-то похожи. Но вычисленный размер файла оказался несколько короче. В чем дело?
       Будем искать отличия в нулевом блоке от такой же информации в программе DUMP. Вроде бы все похоже, но чисел больше. Например, в ячейке 44 вместо 000000 записано 021000 (или в других подобных программах 001000). Какой-нибудь признак? Да! Именно он (001000) говорит о том, что размер файла больше, чем размер ОЗУ, занимаемый программой.
       Такие программы называются оверлейными, или программами с перекрытиями. Идея состоит в том, что совсем не обязательно хранить в ОЗУ всю программу. Можно загрузить только основную часть — корневой сегмент, а фрагменты программы, реализующие отдельные функции — оверлейные сегменты, — загружать на одно и то же место в памяти по мере необходимости. Изобразим на рисунке, как выглядит файл программы и программа, загруженная в память процессора.

      /""""""""""""""""""""""""""""""""""""""""""""""""""""/
     /                Ф А Й Л Ы    н а   н о с и т е л е  /
    /             /"""""""""""""""""""""""""""""""""""""""
   /             /
  /             /
  I""""""""""""I
  I оверлейный I
  I сегмент  3 I
  I............I
  I""""""""""""I
  I            I
  I оверлейный I
  I сегмент  2 I
  I            I
  I............I     ' ' ' ' ' ' ''!""""""""""""!' ' ' ' ' ' ''
  I""""""""""""I     I""""""""""""!!            !'            '
  I            I     I            !!            !!""""""""""""I
  I оверлейный I     I оверлейный !! оверлейный !! оверлейный I
  I сегмент  1 I     I сегмент  1 !! сегмент  2 !! сегмент  3 I
  I............I     I............!!............!!............I
  I""""""""""""I     I""""""""""""I
  I            I     I            I
  I  корневой  I     I  корневой  I
  I  сегмент   I ==> I  сегмент   I
  I            I     I            I
  I------------I     I------------I     П Р О Г Р А М М А
  I   BLOCK 0  I     I   BLOCK 0  I     в памяти процессора
  +------------+     +------------+

       Для того чтобы система знала, каким образом выделять память для программы, и предназначены те дополнительные числа в нулевом блоке.
       Размер программы, как и раньше, записан в 000050 ячейке, как и раньше, он определяет размер оперативной памяти процессора для программы и равен соответственно сумме размеров корневого сегмента и самого большого оверлейного сегмента.
       Но системе для работы необходима более полная информация:
       — Адрес памяти, куда каждый оверлейный сегмент должен загружаться.
       — Номер блока в файле, с которого начинается каждый оверлейный сегмент.
       — Сколько слов необходимо прочитать из файла, чтобы весь оверлейный сегмент оказался в памяти?
       Понятно, что при большом количестве оверлейный сегментов эту информацию удобнее хранить в виде таблицы, адрес которой указан в ячейке 000064. Этот адрес указывает, как правило, в область первого блока, к которому стоит повнимательней приглядеться.
       Если наша программа действительно оверлейная, имеет тип .SAV и предназначена для работы в SJ-мониторе, то в ячейке 001000 содержится код 060502, что в коде RADIX-50 отображается, как "OVR" = OVERLY.
       Во-вторых, как мы уже сказали, по адресу, указанному в ячейке 000064, находится таблица параметров оверлейных сегментов. Для нашего случая (программа DUP.SAV V5.1) этот адрес равен 001106. Набор чисел в этой таблице также может быть узнан по характерному ритму. Первое слово указывает на адрес в ОЗУ для загрузки оверлейного сегмента. Второе — указывает на номер блока в файле, с которого начинается оверлейный сегмент, и третье слово — счетчик слов, т.е. размер оверлейного сегмента в словах. Учитывая этот ритм, перепишем таблицу, как показано ниже.

       001106/  010560 000011 002354
       001114/  010560 000016 001565
       001122/  010560 000022 001164
       001130/  010560 000025 002144
       001136/  010560 000032 001617
       001144/  010560 000036 002430
       001152/  010560 000044 001355
       001160/  010560 000047 002420

       Но как же найти конец этой таблицы? Конечно же, по нарушению ритма. Дело в том, что следом идет другая таблица, которой мы до поры до времени заниматься не будем. И эта таблица имеет другой, так же явно выраженный ритм:

  004357, 001002, 000###, 0#####.

       Таким образом, по параметрам последнего оверлейного сегмента можем определить размер файла (а начало мы его уже нашли). В нашем случае начальный номер блока последнего оверлейного сегмента равен 47, его размер равен 2420 слов или 5040 байтов. И так как он занимает неполные 6 блоков, то размер файла равен:

       47 + 6 = 55 блоков,

       а распечатка каталога показывает, что мы правы.
       — И других видов программ нет?— спрашивает Алеша.
       — Конечно, есть,— отвечаю я,— но в других видах программ ее тип уже указан в нулевом блоке в коде RADIX-50.
       Например, оверлейные сегменты можно хранить не на носителе, а в дополнительной памяти процессора. Такие программы называются виртуальными и уже в нулевой ячейке содержат признак "VIR" (RADIX-50 = 105372). А в остальном все так же, как с обычной оверлейной программой.
       Но есть программы, которые можно загружать в любые адреса памяти. Такие программы имеют тип .REL (RELocation — перемещать). Они могут быть как обычными, так и оверлейными. Отличаются они тем, что имеют таблицу, по которой система сама исправляет программы в памяти перед их выполнением. Таким образом, вычислив обычным образом размер файла, мы должны еще найти конец таблицы перемещений. Найти его просто — ни один из кодов в таблице не может имет значение -2 или 177776. Именно этот код выбран в качестве признака конца таблицы. Разность между номером следующего блока и номером блока начала файла даст нам размер файла в блоках. Осталось внести запись в каталог.
       Однако и в этом случае в нулевом блоке есть необходимый нам признак. Если распечатать дамп нулевого блока, отображающий коды RADIX-50, то в ячейке 000060 мы увидим слово "REL". А в следующем слове номер блока, с которого начинается таблица перемещений.

 

5.8. А если быть последовательными,
или
Файлы на магнитной ленте

       Все, что мы рассматривали до сих пор, — это были устройства файловой структуры с произвольным доступом. Но есть еще группа устройств, при работе с котором неэффективно писать или читать информацию из произвольных мест носителя. Хотя бы потому, что может быть очень большое время поиска этого места. В основном это накопители информации на магнитной ленте.
       Они входят в группу устройств файловой структуры лишь потому, что определение имени и типа файла как метки, по которой его можно найти, имеет смысл. В остальном же файловая структура магнитных лент весьма своеобразна и отлична от принятой в RT-11 для дисков.
       Наиболее распространенный носитель — катушечная магнитная лента — используется на различных магнитофонах и с различной плотностью записи. Для работы с ними в RT-11 используется файловая структура, определенная в стандарте ANSI X3.27 уровень 1 (ANSI — American National Standards Institute — Американский Национальный Институт Стандартов). Главное отличие от файловой структуры дисков — отсутствие каталога как такового. Вместо него используется соответствующие метки файлов, в которых записана информация о файле, а также метка тома, содержащая (подобно первому блоку на диске) информацию о томе.
       То, о чем мы так долго говорили — где файл начинается и где кончается, — в данном случае описывается прямо — с помощью метки начала файла (HDR1) и метки конца файла (EOF1). А чтобы данные нельзя было спутать с метками, они заключаются как бы в скобки специальными кодами, которые принято называть ленточными маркерами (TAPE MARK) и которые мы будем условно обозначать звездочкой (*). Таким образом, структуру файла на магнитной ленте условно можно изобразить так:

  HDR1 * ДАННЫЕ * EOF1 *

как видно — после метки конца файла также записывается ленточный маркер.
       Однако мы упомянули о метке начала тома (VOL1) и поэтому покажем полную структуру ленты с одним файлом

  VOL1 HDR1 * ДАННЫЕ * EOF1 * * *

и с двумя файлами

  VOL1 HDR1 * ДАННЫЕ * EOF1 * HDR1 * ДАННЫЕ * EOF1 * * *

       Нетрудно заметить, что метка конца файла сопровождается ленточным маркером, а также то, что конец ленты определяется по дополнительным двум идущим подряд ленточным маркерам. Здесь же следует отметить, что такой признак конца тома (EOF1 и три ленточных маркера) всегда записывается при закрытии КАЖДОГО файла. А отсюда можно сделать вывод — любой записанный на магнитную ленту файл является последним! Это очень важно понять. Файлы могут оказаться недоступными только потому, что кто-то записал очередной файл в середину ленты.
       И еще один момент необходимо отметить. При перемотке и поиске информации на магнитной ленте основным разделяющим признаком является ленточный маркер, а дополнительным — метки начала и конца файла. Вследствие этого мы не можем перемотать ленту назад на один блок (управляя из KMON), несмотря на то, что данные записаны поблочно. Можно вернуться только на одну (две, три и т.д.) позиции, занимаемые файлами, а затем, перемещая ленту в прямом направлении, по метке начала файла найти необходимый файл.
       Каталог магнитной ленты составляется путем чтения информации из меток VOL1, HDR1, EOF1. Вместо начального номера блока в листинг выводится последовательный номер файла, называемый позицией. Размер файла определяется путем подсчета количества блоков данных, которое затем проверяется по данным в метке конца файла. Таким образом, лента, не содержащая никаких файлов после инициализации, имеет следующий формат:

  VOL1 HDR1 * * EOF1 * * *

       и так как программы ОС, реализующие отдельные функции, должны находиться на устройстве с произвольным доступом, то мы пока не будем говорить о загрузке с магнитной ленты, хотя такая тоже возможна, а сразу перейдем к описаниям меток.
       Каждая метка занимает 80. байт, как одна перфокарта, хотя на ленте для нее отводится один 512.- байтовый физический блок. И так как вся информация указана в коде ASCII, то ее удобно читать с помощью программы DUMP.
       В ниже приведенных таблицах использованы следующие стандартные обозначения:

CP
       — позиция символа в метке

FIELD NAME
       — указатель имени поля

LENGTH
       — длина поля в байтах

CONTENT
       — содержание поля

VOlume header Label (VOL1) - метка начала тома

CP FIELD NAME LENGTH CONTENT
1 - 3 идентификатор метки 3 VOL
4 номер метки 1 1
5-10 идентификатор тома 6 Метка тома. Если вы не указали идентификатор тома во время инициализации, то по умолчанию "RT-11A"
11 Связка 1 <ПРОБЕЛ>
12-37 Зарезервировано 26 <ПРОБЕЛЫ>
38-50 Идентификатор владельца 13 CP38 = D \ это значения для лент
      CP39 = % ! записанных фирмой DEC
      CP40 = B / для PDP-11
      CP41-50 имя владельца максимум 10 символов. По умолчанию <ПРОБЕЛЫ>
51 Стандарт версии DEC 1 1
52-79 зарезервировано 28 <ПРОБЕЛЫ>
80 Стандартная версия метки 1 3

 

file HeaDeR label (HDR1) - метка начала файла

CP FIELD NAME LENGTH CONTENT
1 - 3 идентификатор метки 3 HDR
4 номер метки 1 1
5-21 идентификатор файла 17 6 символов ASCII имени файла, точка, 3 символа типа файла. (вы можете дополнить символом <ПРОБЕЛ> имя файла до 6 символов
22-27 Идентификатор установки файла 6 RT11A<SPACE>
28-31 Номер секции файла 4 0001
32-35 Последовательный номер файла 4 первый файл на ленте имеет 0001 значение увеличивается на 1 для каждого последующего файла. В только что инициализированной ленте это значение равно 0000.
36-39 Номер генерации 4 0001
40-41 Версия генерации 2 00
42-47 Дата создания 6 <ПРОБЕЛ> и следующие за ним последние две цифры года, умноженный на 1000 плюс номер дня в ASCII; <ПРОБЕЛ> и следующие за ним 00000, если нет даты. Для примера, 2/1/75 запоминается как <ПРОБЕЛ>75032.
48-53 Срок хранения 6 <ПРОБЕЛ> и 00000 указывают на истекший срок хранения файла.
54 Доступность 1 <ПРОБЕЛ>
55-60 Счетчик блоков 6 000000
61-73 Код системы 13 DECRT11A<SPACE>
74-80 Зарезервировано 7 <ПРОБЕЛ>

 

first End Of File label (EOF1) — Метка конца файла

CP FIELD NAME LENGTH CONTENT
1 - 3 идентификатор метки 3 EOF
4 номер метки 1 1
5-21 идентификатор файла 17 6 символов ASCII имени файла, точка, 3 символа типа файла. (вы можете дополнить символом <ПРОБЕЛ> имя файла до 6 символов
22-27 Идентификатор установки файла 6 RT11A<SPACE>
28-31 Номер секции файла 4 0001
32-35 Последовательный номер файла 4 первый файл на ленте имеет 0001 значение увеличивается на 1 для каждого последующего файла. В только что инициализированной ленте это значение равно 0000.
36-39 Номер генерации 4 0001
40-41 Версия генерации 2 00
42-47 Дата создания 6 <ПРОБЕЛ> и следующие за ним последние две цифры года, умноженный на 1000 плюс номер дня в ASCII; <ПРОБЕЛ> и следующие за ним 00000, если нет даты. Для примера, 2/1/75 запоминается как <ПРОБЕЛ>75032.
48-53 Срок хранения 6 <ПРОБЕЛ> и 00000 указывают на истекший срок хранения файла.
54 Доступность 1 <ПРОБЕЛ>
55-60 Счетчик блоков 6 Номер последнего блока данных, начиная от метки HDR1.
61-73 Код системы 13 DECRT11A<SPACE>
74-80 Зарезервировано 7 <ПРОБЕЛ>

       Так как данный стандарт определен для любых операционных систем, то естественно в метках есть поля, которые RT-11 не использует, например срок хранения файла. Использование кода ASCII для меток, а также то, что они ограничивают файл с обеих сторон, позволяет определить характеристики файла, даже если предыдущие файлы испортились и программа DIR не может собрать их в каталог. Однако здесь мы не можем вносить запись в каталог ввиду отсутствия такового. Но мы можем скопировать файл, если знаем его номер (позицию) на ленте.
       Кроме того, необходимо из полученной информации сделать следующие выводы:
       — На одной ленте может быть несколько файлов с одним именем и типом. Это может привести к некоторым затруднениям при копировании, если используется имя файла. В этом случае в качестве указателя лучше использовать его позицию.
       — Эффективность использования логических дисков при записи на ленту можно достаточно точно рассчитать. Размер каталога — 8 блоков, а каждый файл на ленте требует дополнительно по два блока для меток (HDR1 и EOF1). Таким образом, если мы хотим записать на ленту более 5 файлов, то лучше организовать из них логический диск и записывать его одним файлом. Дополнительные расходы памяти на ленте для каталога окупаются отсутствием лишних меток начала и конца файла.
       Ну вот. Теперь по дампу носителя ты сможешь отделить один файл от другого и в некоторых случаях определить, для чего он предназначен. Для восстановления информации тебе нужны только средства для занесения в каталог записи об этих файлах. А о них мы поговорим в следующие разы.

(c) 1992г Архангельский Андрей Германович




Поддержите культуру
ЯндексЯндекс. ДеньгиХочу такую же кнопку

Google
 
Web azdesign.ru az-libr.ru


Дата последнего изменения:
Wednesday, 23-Oct-2013 09:02:52 UTC