ファイルシステム

提供:UnixClassWiki
2007年11月27日 (火) 16:27時点におけるHironobu (トーク | 投稿記録)による版 (→‎ファイルシステムの構造)
ナビゲーションに移動 検索に移動

ファイルシステムの構造

ここでのファイルシステムは、ファイルを管理するシステム全体のことをいっています。一方、ext2やext3といった下位レベルのレイヤのファイルシステムも同じファイルシステムと 呼ぶが一般的です。これは古典的なUNIXでは、1つのファイルシステムは下位レイヤレベルで1つの形式しか持っていなかったため問題はありませんでした。ところが現在では下位レイヤにいろいろな種類のファイルシステムをもっています。ですから、前後の文脈を理解しておかないとファイルシステムと全体を意味するファイルシステムと、下位レイヤのファイルシステムをうまく用語で区別できない状況にありますし、文中でもそうなり読んでいて混乱しやすいので注意してください。

ツリー構造

Unixのファイルシステムは/を頂点にしたツリー構造です。Windows系のオペレーティングシステムではC:といったようにハードウェアである「ドライブ」を意識した構造になっていますが、Unixでは/を頂点にしたきれいなツリー構造になっています。ディレクトリとはパソコンで言う所のフォルダです。ディレクトリがファイルの属性情報を知っています。ファイル自体はデータのみ入っています。先頭から連続したバイト列になっています。むかしファイルといえば大型汎用機のファイル構成しかなかった時代では説明するのが大変でしたが、今、この辺りは既に感覚的に馴染んでいるので、特に説明する必要はないでしょう。

まずは/にどんなファイルやディレクトリがあるかコマンドlsで見てみましょう。オプション-Fは名前の後ろにキャラクタをつけて、それがファイルなのかディレクトリなのか、あるいは他の属性を持つのかを表現してくれます。

$ ls -F /
bin/	dev/	 home/	  lost+found/  proc/  tmp/  vmlinuz@
boot/	etc/	 initrd/  mnt/	       root/  usr/
cdrom/	floppy/  lib/	  opt/	       sbin/  var/

名前の後ろに/がついているのがディレクトリです。ファイルの後ろに@がついているのはシンボリックリンクです。まず、細かいことを抜いて、外部記憶装置であるハードディスクが、このファイルシステムと対応しているのかというもっとも最初の部分を説明しましょう。WindowsであればC:とかE:といったドライブ名で出てくるので直観的にわかり易いですか、一方でハードウェアを意識せざる得ない構造になっています。

- 主要なディレクトリの意味 -- /bin : システムに最小限必要なコマンド群 -- /dev : デバイススペシャルファイル群 -- /home : 一般ユーザのディレクトリ -- /lost+found : 破損したファイルの断片を退逃させる -- /proc : システムの状況やパラメータをやり取りするファイルのように見せかけたインタフェース -- /tmp : テンポラリディレクトリ -- /boot : ブート時に使用するカーネルが入っている -- /etc : 各種システム設定ファイルのディレクトリ -- /root : ユーザrootのディレクトリ -- /usr : システムに必要なディレクトリ群が入っているディレクトリ -- /sbin : システム管理者に最低限必要なコマンド群 -- /lib : システムに最低限必要なライブラリ群 -- /var : ログファイルやスプールなど用のディレクトリ

むかしのUNIXではディレクトリは特殊なファイルで、catをすると本当に中身を表示できました。現在ではディレクトリはファイルではなく、ディレクトリという特別なファイルシステム上のノード情報という位置付けになっています。これはUNIXのファイルシステムが抽象化されたレイヤ構造になったためです。


ファイルシステムのマウント

MOでもUSBメモリでもハードディスクでも、あるいはファイルであってもブロックデバイスとみなせるものなら同じですが、話を単純化するために、ここではハードディスクということで話を勧めましょう。

ファイルシステムとはファイルを管理するための仕組み全体を指します。ハーディスクのパーティションをext2やext3、あるいはそれ以外のファイルシステムの形式にフォーマットしそれをファイルシステムとしてマウントします。

まずハードディスクのパーティションを設定し、各々のパーティション上にファ イルシステムを構築し(フォーマットし)、そしてマウントします。コマンド dfを使うと、どのパーティションがどのディレクトリにマウントしているのか わかります。このディレクトリをマウントポイントと呼びます。

$ df
Filesystem           1k-blocks      Used Available Use% Mounted on
/dev/hda1             28834716   1593820  25776172   6% /
/dev/hda2             48062468   4817440  40803552  11% /home

/dev/hda1は、IDE 0 Master に接続されるハードディスクの最初のパーティショ ンのことで、hda2は2番目のパーティションを意味しています。ハードディス クをまるごと1パーティションにすることもできます。下の例はSCSI接続され ているMO装置にMOのメディアを入れてマウントしている状態です。ちなみにこ のMOはこのテキスト書いているLinuxマシンに接続しており、主に定期的なバッ クアップに使っています。

/dev/sda                610940    206972    372936  36% /mnt

Linuxでハードディスクに利用できるファイルシステムの種類にはext2、ext3、 JFS、XFS、ReiserFSなど色々な種類が使えます。それぞれに良さがあるのです が、慣れなければ、この中で一番古いext2を使うのが無難でしょう。これらの ファイルシステムは、それぞれ性能や機能に特徴があります。選ぶのに悩むほ どの選択肢が用意されています。これがWindows XPやWindows 2003 Server だ と互換性を持たすためのFATが2種類と、主に使うNTFSの合計3種類で、実質 NTFSの1 種類だけです。

調べてみよう| Linux以前のUnixも一つのオペレーティングシステムは主たる

ファイルシステムは1つだけでした。それは何故でしょう。

ファイルシステムの構築とマウントは非常に簡単です。ハードディスクを指定 してフォーマットし、それとマウントポイントとなるディレクトリへマウント するだけです。

/dev/sdaに接続されているMOデバイスをext2のファイルシステムを構築し、マ ウントする手順は次のようになります。

# /sbin/mkfs -t ext2 /dev/sda
# /bin/mount -t ext2 /dev/sda /mnt
# df /mnt/mo
Filesystem           1k-blocks      Used Available Use% Mounted on
/dev/sda                610940       256    610684   1% /mnt

まだ何も使っていない状態でも、ファイルの属性情報を管理するのに必要な領 域が既に事前に取られています。

# cd /mnt 
# ls -l
total 12
drwx------    2 root     root        12288 Nov 25 21:21 lost+found

ext2の場合、フォーマットしたパーティションに(今回の説明では1ディスク1 パーティション)lost+foundというディレクトリができます。このディレクト リはハードディスクの故障などで内容が破損してしまったファイルの残骸が格 納されます。


inode

Unixのファイルシステムは"/"を頂点としたツリー構造で一意のファイルを指 定するにはファイルパスを使いますが、ではカーネルの中ではどう扱っている のでしょうか?

カーネル内部ではファイルの実体は/home/hironobu/text.txt というファイル パスで管理しているのではなくinodeというノード番号を使って管理していま す。しかしユーザ側からアクセスをするのはファイル名(正確にはファイルパ ス名ですが)を指定しますので、inode番号を使ってアクセスするようなことは できません。ls -iを使えばinode番号が表示されます。

$ ls -i *.txt
540463 memo.txt        540446 section-4.txt   540452 section-8.txt
540402 section-1.txt   540444 section-5.txt   
540416 section-2.txt   540420 section-6.txt
540443 section-3.txt   540447 section-7.txt

inode番号はディレクトリ中にあるファイル名とinode番号を管理するデータ構造 struct dirent [1] に格納されています。 カーネル内の関数nameiによりファイル名はinode番号に変換されます。


inode番号を直接扱えばより効率的ではないかと思う人もいるかも知れません。 理屈を考えると大型汎用機のようにファイル資源を固定的に指定できるような システムの方が、一度ファイル名からファイル資源を示すデータへ変換するよ うなUnix流よりもコストが低いといえるでしょう。しかしこのコストは現在の ハードウェア事情を勘案すると実にわずかなものです。一方で名前空間による 柔軟なファイル管理の方が議論の余地なくオペレーションのコストが低いと言 えるでしょう。かくしてトータルで考えるとファイル名で扱う方がコスト的に 有利なのです。


補足
ここでオペレーティングシステムの「コスト」とは、システムが動作するコストだけではなくオペレーションも含んだコストであると認識してください。


inode自体は struct inode [2] を参照するとわかりますが、ファイルの属性に関する情報などを持っています。 一方でユーザはinode番号はわかりますがinodeが持っている情報には直接アク セスできません。 ファイルのユーザ属性を変えたり、あるいは情報を獲得するにはchmod(2)、stat(2)と いったシステムコール経由でアクセスするしかありません。 これはLinuxのような今日的なUnix系のオペレーティングシステムでは、 複数のファイルシステムの方式を同時に持っているからです。


VFS

複数のファイルシステム方式があるのに、何故ユーザは統一したインタフェー スでファイルにアクセスできるのでしょう? それはVFS (Virtual File System) [3] が用意されているからです。

+------------------------------+s
|           ユーザ             |
+------------------------------+ 
|              VFS             | ^  
+----+----+---+---+---+--------+ | ファイルシステム
|ext2|ext3|JFS|FAT|NFS|.....   | V
+----+----+---+---+---+--------+
|     バッファキャッシュ       |
+------------------------------+
|ハードウェア     |ネットワーク|
+-----------------+------------+


VFSは個々のファイルシステムとユーザの間のクッションの役目を果たしてお り、ユーザ側からはVFSしか見えないようになっています。このVFSがファイル システム間の違いを吸収し、統一したインタフェースをユーザ側に提供します。


むかしむかしのUNIXはディレクトリとファイルのアクセスの違いはありません でした。ディレクトリはシステムがファイルを管理するための内容を持ったファ イルでしかありませんでした。ファイルシステムが1種類しかなく自分のマシ ンに接続するハードディスク上にあった頃は、これでも十分ですが、複数のファ イルシステムが存在する場合はそうもいきません。機能や仕様が個々に違う、 すべてのファイルシステムに同じ方法でアクセスすることを提供しなければい けません。


VFSのようなファイルシステムの上に仮想的なファイルシステムを加えて統一 したインタフェースを作ったのは1980年代後半にSUN MicrosystemsがNFS (Network File System)のために作ったのが最初です。別のマシン上にあるファ イルシステムをネットワーク経由でマウントできるようにするには、このよう な方法が適切だからです。


VFSの下に位置するファイルシステムは、少なくともカーネルのソースコード をチェックする限り30以上あります。個々のファイルシステムがどこまで利用 可能なのか、つまり、常用のファイルシステムとして使えるのか、互換性のた めに残しているのか、あるいは読み込みだけで書き込みができない、あるいは 一部の機能しか使えないなどに関しての資料が見当たらないので一概に30以上 というのは不適切かも知れません。次によく使われるファイルシステムを取り 上げて説明してみましょう。

ファイルシステム

ここでは下位レイヤでのファイルシステムを個別に説明します。

ext2 ファイルシステム

ext2ファイルシステム [4] は正式名称Second Extented Filesystemといい、ext2fs とも書きます。Linuxのために開発されたファイルシステムです。前身である Ext ファイルシステムの次のバージョンと位置づけられます。最大ファイルシ ステムサイズ4TB、最大ファイルサイズ2GB まで扱えます。


ext2ファイルシステムは関連するファイルをブロックグループと呼ばれるグルー プに分割される。そのブロックの中にブロック属性情報やinode情報、そして ファイルの内容を書くブロックを保存している。


+-----------+---------+---------+---------+---------+
|ブート領域 |ブロック |ブロック |         |ブロック |
|           |グループ1|グループ2|.........|グループN|
+-----------+---------+---------+---------+---------+


ext2ファイルシステムはファイルの読み書きで良い局所性を出すための工夫が されています。書き出しが行われる時、同じブロックグループ内で、隣接する 8ブロックを先行して割り当てするので、連続しての書き込みの効率があがり ます。このような書き方をするので当然、連続しての読み込みをする際のヒッ ト率が高くなります。



ext3 ファイルシステム

ext3 [5] ext2をベースにジャーナリングファイルシステム(Journaling Filesystem)に 拡張したものです。ジャーナリングファイルシステムとはメタデータと呼ばれ るファイル属性などの変更履歴をジャーナルログに記録しておき、ファイルシ ステムの整合をチェックする時は、そのジャーナルを使う方式です。ext2ファ イルシステムのように整合性をチェックするためにファイルシステム全部を走 査する必要がないので高速に処理ができます。最大ファイルシステムサイズ 4TB、最大ファイルサイズ4TBまで扱えます。


ext3と比べるべきファイルシステムとしてIBM社が開発したJFSファイルシステ ム、Reiserファイルシステム、あるいはSGI社が開発したXFSファイルシステム などもあります。これらはいずれもジャーナリング機能を持っており、かつ、 色々な特色ある機能を持っています。


ISO9660 ファイルシステム

CDROMの規格であるISO9660のファイルシステムです。このファイルシステムを 指定してマウントすると、CDROM (もちろんISO9660であること) をリードオン リーのファイルシステムと認識されます。類似のファイルシステムにJPLIETファ イルシステムやZISOFSファイルシステム、DVD用のUDFなどもなどもあります。


tmpfs、ramfsファイルシステム

メモリ上に展開するファイルシステムです。メモリ上にあるのでシステムが停 止すれば、なくなります。たとえばLiveCDのようにハードディスクを使えないような場合に、メモリ上にファイルシステムを構築する際に利用されます。

NFS / CODA

NFS (Network filesystem) はUnixで最初に使われたネットワークを経由して ファイルシステムをマウントする仕組みです。NFSの仕様はUNIXだけではなく 抽象化したファイルシステムとなっています。たとえば異なるUnixの種類同士 (例えばFreeBSDのファイルシステムとLinuxとか、あるいはSUN Solarisと SystemV IIIとか)、あるいはUnixとWindowsといったファイルシステムの種類 の異なるものでもネットワークを介して共有することができます。LANで接続 されたコンピュータ間でファイルを共有することを想定しています。


CODA [6] はNFSと同様にネットワークを経由してファイルを共有する仕組みです。 NFSは古典的なUnixのファイルシステムをネットワーク上に延長してきたとい えますが、CODAはネットワークがまずありきの設計になっています。モバイル コンピュータでも使えるようにネットワークが切り離されても動きますし、サー バの複製などもできます。かなり近代的かつ、使い勝手が良いシステムに出来 上がっています。


ハードリンクとシンボリックリンク =

さて予備知識が必要なために、少々後回しになりましたがハードリンクとシンボリックリンクの話を始めます。


ある名前を付けられたシンボリックリンクはファイルのように見え、読み書き などができます。しかし、シンボリックリンク自体は実体を持たず、名前で別 のファイルを参照しています。Windows XPなどのショートカットと同じような ものです。


ハードリンクはファイル名で既にアクセスする実体を、他のファイル名でもア クセスできるようにする仕組みといった方がいいかも知れません。ここでの実 体、つまりinode で参照できるファイルの内容です。


この違いは、シンボリックリンクをしている先のファイルを消すのと、ハード リンクしている先のファイルを消すにわかります。シンボリックリンクの先の ファイルを消してみましょう。


$ echo 'abcd' > i
$ cat i
abcd
$ ln -s i t
$ ls -l
合計 4
-rw-r--r--  1 hironobu hironobu 5 2005-11-21 20:12 i
lrwxrwxrwx  1 hironobu hironobu 1 2005-11-21 20:12 t -> i
$ cat t
abcd
$ rm i
rm: remove 通常ファイル `i'? y
$ cat t
cat: t: そのようなファイルやディレクトリはありません


ファイルiをシンボリックリンクしているtは、ファイルiが存在しないとtを参 照しても、ファイルが存在しないとなりエラーとなります。次はハードリンクです。ハードリンクはiを消してもファイルの実体をtが指し ているので、ファイルの中身はまだ存在しています。

$ echo 'abcd' > i
$ ln i t
$ ls -li
合計 8
-rw-r--r--  2 hironobu hironobu 5 2005-11-21 20:14 i
-rw-r--r--  2 hironobu hironobu 5 2005-11-21 20:14 t
$ ls -li
合計 8
8488913 -rw-r--r--  2 hironobu hironobu 5 2005-11-21 20:14 i
8488913 -rw-r--r--  2 hironobu hironobu 5 2005-11-21 20:14 t
$ rm i
rm: remove 通常ファイル `i'? y
$ cat t
abcd
$ ls -il
合計 4
8488913 -rw-r--r--  1 hironobu hironobu 5 2005-11-21 20:14 t


lsコマンドの i オプションはinode番号の表示です。lsコマンドの表示の最初 8488913がinode番号です。パーミッション"-rw-r--r--"の後の数字は、ファイ ル実体への参照リンク数を表しています。最初のiとtがある時は、その実体を 参照している数は2です。ファイルiを消すと、数が減るので1になります。