恐竜本10章です。この章ではファイルシステムの機能紹介や概念紹介をしています。割りとPCを使っていれば知っている話が多く、詳しい中身の話は11章みたいなので今回は内容が薄いです。
ファイルの概念
ファイルはデータの論理的な単位である。ファイルは内部構造を持っている。あるファイルはテキストだったり、ソースコードだったり、オブジェクトファイルだったりする。また、ファイルにはいくつかの属性がある。
- 名前 人に理解しやすい形式になっている
- 識別子 これは人にとって読みやすい形式とは限らない
- タイプ
- 場所
- サイズ
- アクセス保護
- 日付時刻、作成者
ファイルに対してはいろいろな操作が定義されている。
- 作成
- 書き込み
- 読み込み
- ファイル内の位置変更
- 削除
- 切り詰め
などがある。また、ファイルを開くという動作は、OSがストレージシステム上の当該ファイルの位置を探し出す行為に対応しており、書き込んだり読み込んだりする前に予め場所をとっておくことで毎回やる必要をなくす意味合いがある。また、開かれているファイルのリストを作成し、他のプロセスからのアクセス保護を行う意味もある。閉じるという動作は現在オープン中のファイルを解放し、取得しているロックを解放する。まとめると、ファイルを開いたり閉じたりするということは、読み書きに必要な以下のデータを初期化したり破棄したりすることに当たる。
- ファイル中の現在位置
- ファイルオープン数
- ファイルのディスク上の位置
- アクセス権
ファイルの種類
ファイルには様々な種類がある。テキストファイルや実行可能ファイルなどである。これを識別する一般的な方法には、ファイル名の末尾に拡張子をつけるというものがある。また、UNIXではファイル自体の先頭にマジックナンバーというデータが存在している場合、それを使って種類を識別したりする。
Macintoshではresource forkとdata forkという構造を持つファイルをサポートしている。resource forkにはプログラムが表示するボタンのラベル情報などが含まれており、ユーザーが好きに書き換えられる。一方data forkにはプログラムコードやデータが入っている。
あるファイルの特定のオフセットがディスク上でどこにあるか特定するのはやや複雑である。というのも、ディスクはブロックサイズ単位でしかI/Oできないことが多く、ファイルのサイズはブロックサイズの整数倍ということはあまりない。そのため、論理レコードを同じブロックにパッキングすることがよく行われるからである。また、ブロック単位でしかI/Oできないということはブロック内に空きがあっても有効活用できないinternal fragmentationが起こりうることを意味している。
アクセス方法
ファイルの情報へのアクセス方法としては様々存在する。シーケンシャルアクセスでは、現在位置から目的位置までデータが記録されている順番にアクセスする。これはテープモデルに基づいている。一方、ダイレクトアクセスでは、ファイルは論理レコードからなり、プログラムはどんな順番でもアクセスできる。これはディスクモデルにもとづいている。
その他のアクセス方法としては様々なブロックへのポインタを保持したインデックスを作成するというものもある。これはダイレクトアクセスを前提としている。インデックスが大きくなりすぎるとインデックスのインデックスを作ったりする。
ディレクトリとディスク構造
ディスクは複数の区画にパーティショニングすることができる。それぞれのパーティションでは異なるファイルシステムを持つことができる。パーティショニングはそれぞれのファイルシステムのサイズを限定したり、一部をファイル保存以外の用途、例えばスワップ空間に使ったりするのに役立つ。ファイルシステムを含むものをボリュームと言ったりする。それぞれのボリュームにはデバイスディレクトリ(単にディレクトリということが多い)が含まれており、どのファイルがどこに置いてあるかが記録されている。
ファイルシステムには様々な種類がある。tmpfs, objfs, ctfs, lofs, procfsなどである。以降では汎用のファイルシステムであるufs,zfsなどを念頭に話を進める。
ディレクトリはファイルの管理情報を集めたものである。以下のような操作がディレクトリに対して行われる。
- ファイルの検索
- ファイルの作成
- ファイルの削除
- ディレクトリ内のファイル列挙
- ファイル名変更
- ファイルシステムのトラバーサル
以上の操作を行うため様々なディレクトリ構造が考案されている。
シングルレベルディレクトリでは、ディレクトリの下にファイルが存在しており、ディレクトリの入れ子は行わない。この場合だと複数人でコンピュータを使うとき名前の衝突がおきやすかったりする問題がある。
ツーレベルディレクトリではuser file directory (UFD)とmaster file directory (MFD)とに分ける。MFDエントリーはユーザーごとに作成され、各MFDはUFDを複数個保持できる。各UFD直下にはファイルが置かれる。UFDがユーザーごとに作られるので複数人のユーザーが同じファイル名を使っても問題ない。この方法で問題となるのが、システムファイルの扱いである。全ユーザーで同じファイルを使う必要があるが、ユーザーごとにファイルを管理すると、システムファイルを使いたいとき全ユーザーに同じファイルを持たせなければならなくなる。これを回避する方法としては、システムファイルは特殊ユーザーが保持しているとして扱う。各ユーザーがそれを必要とした場合は、まずUFDを探し、なければ特殊ユーザーのディレクトリを探す。
木構造ディレクトリでは、ディレクトリがディレクトリを保持でき、任意の深さの木構造を形成する。それぞれのプロセスは現在プロセスが実行されているディレクトリという概念を持ち、それをカレントディレクトリと呼ぶ。ユーザーはカレントディレクトリを好きに変更できる。また、ファイルが置かれた位置を示すパスは絶対パスと相対パスとで表すことができる。絶対パスはルートノードからの位置関係を示し、相対パスはカレントディレクトリからの位置関係を表す。木構造ディレクトリではディレクトリの削除ポリシーがOSによって異なる。子としてファイルを含むディレクトリを消すことを許可するかしないかはOSの設計思想による。
非巡回グラフディレクトリでは、あるファイルのリンクを作ることができる。リンクは色々なディレクトリに置くことができ、同一ファイルを指し示す。ファイルを読み込むときはリンクを解決する必要がある。同じファイルを共有するためにファイルをコピーしたら、各コピーが変更されるたび同期が必要であるが、リンクではそれが不要であるのが利点である。このディレクトリ構造ではファイルの検索や統計を取ったりするためにリンクを解決する必要があり複雑となる。また、元ファイル削除時に残されたリンクをどう扱うかが問題となる。シンボリックリンクではリンクが残り、リンクを使ってアクセスしようとすると、もともと指し示したファイルが存在しないことが検知されその段階でエラーとなる。一方ハードリンクではそもそもリンクを残してファイルを消すことが許可されず、まずすべてのリンクを消してから元ファイルを消すこととなる。
ディレクトリが巡回グラフとなるようにすることもできる。この場合はディレクトリトラバーサル時に無限ループとならないようにする必要がある。また、非巡回グラフの場合はあるファイルを参照しているディレクトリが0となればそのファイル領域には新たなデータを書き込んで良いが、巡回グラフだと自己への参照が起こりうるのでカウントが0以外でも新たなデータを書き込んで良い事がある。このようなファイルが溜まるとストレージが圧迫されるのでガベージコレクション機構が必要となる。また、ディレクトリトラバーサル時にはリンクを無視することで無限ループを回避できる。
ファイルシステムのマウント
ファイルを読んだり書いたりする前に開く必要がある用に、ファイルシステムも開かなければならない。ファイルシステムを開く行為をマウントという。ファイルシステムをマウントするときには、マウントポイントと呼ばれる、ファイルシステムと紐づくパスを与える。次にOSはマウントするように指示を受けたデバイスに関して認識可能なファイルシステムを持っているかを確認する。確認後そのマウントポイントにファイルシステムがマウントされたとして登録する。
ファイルの共有
OSのユーザーは複数人いることが想定されるので、各ファイルのアクセス権を設定できなければならない。これを実現するため、ファイルやディレクトリに対してはオーナーとグループという概念が存在している。オーナーはファイルのアクセス権を変更できるユーザーであり、そのファイルについて最も大きな権限を持っている。グループはそのファイルが共有されているユーザーのグループを意味している。
ネットワークの進展によって、遠隔的なファイル共有も行われるようになった。まず実装された方法はFTPであり、これは送信側が手動でファイルを送る。次にメジャーな方法は分散ファイルシステム(DFS)である。DFSではローカルのマシンからリモートのファイルが見える。
遠隔ファイルシステムではクライアントマシンとサーバーマシンが登場するが、これらを簡単に管理できるよう分散情報システムが存在している。domain name system (DNS)ではインターネット上のホスト名からネットワークアドレスへの変換サービスを提供している。他の分散情報システムとしてはSun Microsystemsのyellow pagesなどがある。
Microsoftのcommon Internet file system (CIFS)ではユーザー名やパスワードの情報もやり取りされ、ネットワークログインが実装されている。これによりアクセス許可を与えるか否かが判断されている。ユーザーの情報を組織で共有するためActive Directoryという技術が使われている。Active Directoryはlightweight directory-access protocol (LDAP)を用いている。
ファイル管理系のシステムコールは様々な理由で失敗することがありうる。これに対処するため、状態情報をクライアントとサーバーで維持管理する必要がある。より単純なアプローチとしてはNFSのようにステートレスにしてしまうというものもある。ただし、よりセキュリティは低くなる。
ファイルの共有においてはconsistency semanticsをどう設計するかが重要である。すなわち、同じファイルを複数人が開いているとき、あるユーザーの変更が他のユーザーにすぐ反映されるかどうかという問題を考えなければならない。UNIXでは書き込みはすぐに他のユーザーに反映される。また、オープンモードによっては、ファイル中の現在位置がユーザー間で共有される。AFSでは書き込みは現在同じファイルをオープン中の他のユーザーに反映されない。ファイルが閉じられた場合は、その後にそのファイルをオープンするユーザーからは変更が見える。他のアプローチとしては、イミュータブルな共有ファイルというものがある。作成者があるファイルをsharedとした場合、ファイル名と内容の変更が不可能になり、他のユーザーと共有される。
ファイル保護
ファイルの保護といった場合、物理的な保護と権限のないアクセスからの保護という意味がある。前者はデータのバックアップなどで対処する。後者は様々な方法で提供される。
アクセスからの保護に関しては、すべてのアクセスを完全に禁止すれば保護としては完全になるが、利便性は0となる。すべてのアクセスを許可すると何も保護できなくなる。そのため、ちょうどいいアクセス権の設定が必要となる。アクセス権には以下のようなものがある。
- 読み込み
- 書き込み
- 実行
- 追加
- 削除
- 列挙
コピーやリネームなどは上記動作の組み合わせで表現できるので、上記へのアクセス権を設定できれば良い。これを実現するには、access-control list (ACL)というものが用いられる。ACLはそれぞれのファイルに関してユーザー名と許可されたオペレーションが含まれている。これの問題点はすべてのユーザーに対して設定を書かなければならないので、リストが長くなり作成に労力が必要だったり、事前に全ユーザーがわからない場合に使えなかったり、ディレクトリのエントリーサイズが可変になってディスク管理が煩雑になったりするなどが挙げられる。よりアクセス権設定を凝縮するには、オーナー、グループ、それ以外、の3種類のアクセス権を設定する方法がとられる。
他のアクセス権管理の方法としてはファイルごとにパスワードを設定するなどが考えられる。この場合はパスワードの数が膨大となり、使い回しが発生しセキュリティ上結局問題が出たりするなどが起こりうる。
コメント