2012.4.24
前へ
次へ
ホームページトップへ戻る

復活!CP/M ワンボードマイコンでCP/Mを!
CP/MがTK−80互換のワンボードマイコンの上で復活します
ND80ZVとMYCPU80の上でCP/Mが走ります

[第101回]


●ランダムアクセスファイル

ディスク上に作成されるファイルは一般にはシーケンシャルアクセスファイルです。
媒体としてのディスクはフロッピーディスクであれ、ハードディスクであれ、ランダムにアクセスできる特徴をもっています。
しかし、その上に作成されるファイルのほとんどは、テープに記録されるファイルと全く同じように、先頭から順に読み出すことしかできないシーケンシャルファイルです。
シーケンシャルファイルの作成や読み出しを行なうファンクションコールは[第46回][第56回]で説明をしました。

これに対してランダムアクセスファイルは、レコード単位で順序に関係無く書き込んだり読み出したりすることができます。
ランダムアクセスファイルはどんなときに使われるのか、ちょっと想像がつきにくいように思われます。
身近なところでは、住所録とか名簿を考えてみたらどうでしょうか。
クラス名簿は最初に作成してしまいますから、シーケンシャルファイルかも知れません。
個人の住所録は付き合いが始まったときに新規に追加になりますから、ランダムアクセスファイルに近いものになります。
あいうえお順に並べて作成しても、個人の場合には、五十音すべてが揃うことはまず無いでしょう。
途中が飛んだり、かたまったりします。
一人1枚のカードに作成しておけば、佐藤さんと鈴木さんが並んでいたところに、新しく清水さんを追加することが簡単にできます。
これがランダムアクセスファイルの書き込みに相当します。
シーケンシャルファイルでは、そういうことは簡単にはできません。
たとえば住所録の1行に一人を書いた場合、佐藤さんの次の行が鈴木さんだったとすると、その間に清水さんを追加することはできません。
矢印などをつけて欄外に追記するしかありません。
実際のシーケンシャルファイルでは、コピーを作成しながら途中に追加挿入して新規ファイルを作成する、という方法になります。

ランダムな書き込みといってもでたらめに作成することではありません。
一定のルールがあります。
それが住所録の例でいえば、あいうえお順です。
ただ現実の住所録では、それだけでは困ったことが出てきます。
ひょっとすると伊藤さんや田中さんは二人になってしまうかもしれません。
同姓同名などということも出て来てしまうかもしれません。
ランダムアクセスファイルを作成する場合には、キーが重複することのないように工夫する必要があります。

以上がランダムアクセスファイルについての予備知識です。
CP/Mのランダムアクセスファイルは1セクタが1レコードです。
さきほどの住所録に例えれば、1セクタ(1レコード)が1名の住所氏名カードに相当します。
では名前に相当する検索キーは何になるか、といいますと2バイト16ビットの数値がキーになります。
0000〜FFFFですけれど、実際に使用できるのは、ディスクドライブの最大セクタ数が上限になります。
CP/Mの場合、1台のディスクドライブの最大容量は8MBです。
1セクタ(論理セクタ)は128バイト(1/8KB)ですから、最大セクタ数は64Kになります。
この場合が0000〜FFFFです。
それより小さい容量の場合、たとえば容量が1MBですと、連続して使えるキーとしては0000〜1FFFになります。
十進数では0〜8191です。
それより大きいキーが使えないわけではありませんが、入れ物として2000H個(8192個)の場所しかありませんから、それより大きい数をレコード番号として使うと、途中でディスク容量が足りなくなってしまう場合がでてきます。

どうもいまひとつ、説明がし難いですねえ。
「応用CP/M」(村瀬康治著。アスキー出版局)でも、かなりページを割いて説明されているのですが、なかなか理解できませんでした。

いい例えを思いつきました。
シーケンシャルファイルは1日1行128文字の日記を大学ノートに書くことに例えることができます。
毎日順番に書くことしかできません。
128字に満たないときは、残りを空白にします。
書くことがない日は空白にすることも、その日の行を無くして前に詰めてしまうこともできます。
しかし空白の行を作っても、あとからそこに追記することはできません。
ここが実際のノートとは違うところです。
一度書き込んだらそこには透明なシールを貼って追記ができないようにしてある、とでも考えることにしましょう。

これに対してランダムファイルは128文字が書き込める0から365まで番号がついたカード式の日記帳に例えることができます。
0から365は1月1日から12月31日に1対1で対応しています。
普通は前から順に書いていくことが多いと思いますが、忙しいときや内容がちょいと込み入っているときなどは、あとからまとめて書くこともあると思います。
途中を飛ばして書いても構いません。
書いた日のカードだけをカードボックスに入れます(CP/Mのランダムファイルの場合にはもう少し複雑で、それについては後で説明しますが、週単位での処理を考えます)。

ここが肝心のところなのですが、カードボックスは日付順に整理して入れるのではありません。
作成した順にいれます(CP/Mでの話です。実際のカード式日記でそうするとよいということではありません)。
前にさかのぼって書くこともできますし、すでに書いた日の分を捨ててあとから書き直すこともできます。
あとから追加したカードはカードボックス内の最後に置かれますが、書き換えた場合には、もとのカードが置かれていた位置に置きます。

以上の説明は1日単位の処理についてのお話です。
CP/Mのランダムファイルにはもう少し仕掛けが必要で、実は作成されたカードは1週間分をゴムバンドでまとめてカードボックスに置きます。
書く順番は自由なのですが、ある月のある日のカードを書いたら、その日の週のほかの日のカードは作成していなくても、カードボックスに入れる位置は決定されます(CP/Mのランダムファイルで考えた場合、その週のまだ書かれていない別の日については、白紙のカードを用意して一緒に束ねます)。

うーん。
実例で説明したほうがいいですねえ。
2012年4月のカレンダーです。
第1週は1日〜7日
第2週は8日〜14日
第3週は15日〜21日
第4週は22日〜28日
です。

最初に18日のカードを書いたとします。
カードボックスには記入済みの18日のカードと、日付だけを記入した白紙カードを日付順に並べて、ゴムバンドで束ねて入れます。
赤で示した日付が作成済みのカードで()は日付だけを記入した白紙カードです。
カードボックスにはこの順番に束ねた7枚組みのカードが入ります。
(15)(16)(17)18(19)(20)(21)

次に13日のカードを書いたとします。
するとカードボックスは次のようになります。
(15)(16)(17)18(19)(20)(21) (8)(9)(10)(11)(12)13(14)

カードボックスには、まだ18日と13日のデータしかありませんが、場所としては2週間分がリザーブされたことになります。

次に16日のカードを書くことを考えます。
すると、その場所はすでに確保されていますから(白紙カードが置かれています)、16日の日付だけが記入された白紙のカードにデータを書きます。
その結果は次のようになります。
(15)16(17)18(19)(20)(21) (8)(9)(10)(11)(12)13(14)

まだ3日分しか書いていませんが、消費したカードの枚数は14枚になります。
それがランダムファイルのファイルサイズに相当します。
カードボックスがディスクドライブで、1枚のカードがセクタに相当し、1週間分を束ねたものがブロックです。

実はCP/Mのランダムアクセスファイルにはもうひとつ大きな仕掛けがあります。
上の日記カードの例で説明をします。

カードボックスには、インデックスに相当するところがあって、そこには第1週から54週まで順に番号がついた入れ物があります。

ああ、そうです。
ホテルのフロントにある部屋のキーを置く棚のようなものです。
その棚には、作成済みのカードブロック(上の例では4月第3週と第2週のカード束)をカードボックスに入れた順番を記した番号札が置かれます。
4月第3週が1番、第2週が2番です。

カードを書くときには、最初にこのインデックス棚を見ます。
日付によりそれが第何週に属するかは最初からわかっています。
インデックス棚のその週のところに番号札が置かれていれば、すでに作成済みの週ですから、カードボックスの番号札の位置にその週の束がありますから、その中の日付だけを記した白紙カードに追記します。
あとから、その日のカードを読むときも、同じ手順で行ないます。

カードは週単位で消費されます(ある日のカードを作成した時点で、その日が属する週の他の日付のカードも同時に白紙カードの状態で確保されます)。
ですからインデックス棚に置かれた番号札の最後の番号を見れば、消費したカードの枚数がわかります。
これがCP/Mのランダムファイルのファイルサイズです(消費したカードの枚数が使用済みのセクタ数になります)。
[2012.4.27追記]
何事においても再確認することが必要である、と痛感しました。
確認しないで書くと間違ったことを書いてしまいます。
ここでいう番号札は割当済み(使用済み)のブロックbノ相当します。
しかし、ランダムファイルのファイルサイズではありませんでした。
ランダムファイルのファイルサイズは、上の日記の例で言いますと、作成した一番大きい日付がそのままファイルサイズになります。
たとえば12月31日のカードをただ1枚書いただけで、ランダムファイルのサイズはカード366枚分を示します。
カード1枚が1セクタである、としますと、ファイルサイズは366セクタになります(実際に使用されたセクタ数は1セクタですが、ランダムファイルのファイルサイズは必ずしもそのファイルの実際のサイズを意味しません)。
[追記ここまで]

CP/Mの論理的なドライブの1セクタは128バイトで、1ブロックは8セクタです。
シーケンシャルファイルもランダムファイルも実際にはブロック単位で場所が確保されます。
ランダムファイルはレコードの作成順序は任意(ランダム)ですが、レコードbヘ前から順に8セクタごとに区切られていて、上のカードボックスの例のように、新規に作成されたレコードb含む8セクタ分のブロックがそのときリザーブされます。

上の説明ではブロックを週、セクタを日付カードに例えましたが、それはあくまで例えです。実際のセクタには日付のような通し番号はついていません(トラック毎にセクタbェつけられています)。

次回以降で、実際にテストプログラムを実行して、そのあと、作成されたファイルの中味をダンプして、レコードがどのような順番でデイスクに書き込まれたかを確認します。
そのときに今回の説明をもう一度参照していただくと、より理解がし易いと思います。
なお、実際のCP/Mでの論理ドライブは上で説明しました通り1ブロックが8セクタですが、現行の仮RAMディスクの1ブロックは4セクタです。

とりあえず以上のことを予備知識として理解していただいた上で、次回から実際にランダムアクセスファイルを作成してみることにいたします。

ワンボードマイコンでCP/Mを![第101回]
2012.4.24upload
2012.4.25 一部を書き改めました
2012.4.27追記

前へ
次へ
ホームページトップへ戻る