ファイルシステム
ファイルシステムの構造
ここでのファイルシステムは、ファイルを管理するシステム全体のことをいっています。一方、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 : 破損したファイルの断片を退逃させる (これはファイルシステムが作成するものでLinuxのファイルシステム階層には含まれない)
- /proc : システムの状況やパラメータをやり取りするファイルのように見せかけたインタフェース
- /tmp : テンポラリディレクトリ
- /boot : ブート時に使用するカーネルが入っている
- /etc : 各種システム設定ファイルのディレクトリ
- /root : ユーザrootのディレクトリ
- /usr : システムに必要なディレクトリ群が入っているディレクトリ
- /sbin : システム管理者に最低限必要なコマンド群
- /lib : システムに最低限必要なライブラリ群
- /var : ログファイルやスプールなど用のディレクトリ
むかしのUNIXではディレクトリは特殊なファイルで、catをすると本当に中身を表示できました。現在ではディレクトリはファイルではなく、ディレクトリという特別なファイルシステム上のノード情報という位置付けになっています。これはUNIXのファイルシステムが抽象化されたレイヤ構造になったためです。
Linuxの標準的ファイルシステム階層のスペック(Filesystem Hierarchy Standard)はLinuxファンデーションがドキュメント化しています。[1]
ファイルシステムのマウント
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 [2] に格納されています。 カーネル内の関数nameiによりファイル名はinode番号に変換されます。
inode番号を直接扱えばより効率的ではないかと思う人もいるかも知れません。
理屈を考えると大型汎用機のようにファイル資源を固定的に指定できるような
システムの方が、一度ファイル名からファイル資源を示すデータへ変換するよ
うなUnix流よりもコストが低いといえるでしょう。しかしこのコストは現在の
ハードウェア事情を勘案すると実にわずかなものです。一方で名前空間による
柔軟なファイル管理の方が議論の余地なくオペレーションのコストが低いと言
えるでしょう。かくしてトータルで考えるとファイル名で扱う方がコスト的に
有利なのです。
- 補足
- ここでオペレーティングシステムの「コスト」とは、システムが動作するコストだけではなくオペレーションも含んだコストであると認識してください。
inode自体は
struct inode
[3]
を参照するとわかりますが、ファイルの属性に関する情報などを持っています。
一方でユーザはinode番号はわかりますがinodeが持っている情報には直接アク
セスできません。
ファイルのユーザ属性を変えたり、あるいは情報を獲得するにはchmod(2)、stat(2)と
いったシステムコール経由でアクセスするしかありません。
これはLinuxのような今日的なUnix系のオペレーティングシステムでは、
複数のファイルシステムの方式を同時に持っているからです。
VFS
複数のファイルシステム方式があるのに、何故ユーザは統一したインタフェースでファイルにアクセスできるのでしょう? それはVFS (Virtual File System) [4] が用意されているからです。
VFSは個々のファイルシステムとユーザの間のクッションの役目を果たしており、
ユーザ側からはVFSしか見えないようになっています。
このVFSがファイルシステム間の違いを吸収し、統一したインタフェースをユーザ側に提供します。
むかしむかしのUNIXはディレクトリとファイルのアクセスの違いはありませんでした。
ディレクトリはシステムがファイルを管理するための内容を持ったファイルでしかありませんでした。
ファイルシステムが1種類しかなく自分のマシンに接続するハードディスク上にあった頃は、
これでも十分ですが、複数のファイルシステムが存在する場合はそうもいきません。
機能や仕様が個々に違う、すべてのファイルシステムに同じ方法でアクセスすることを提供しなければいけません。
ファイルシステムの上に仮想的なファイルシステムを加えて統一したインタフェースを提供するようになったのは1984年のSUN MicrosystemsがSunOS 2.0が最初です。[5]
色々なファイルシステムを扱えるフレームワークは、Sunが開発した NFS(Network File System) が別のマシン上にあるファイルシステムをネットワーク経由でマウントするために必要でした。
VFSの下に位置するファイルシステムは、少なくともカーネルのソースコードをチェックする限り30以上あります。
[6]
個々のファイルシステムがどこまで利用可能なのか、つまり、常用のファイルシステムとして使えるのか、
互換性のために残しているのか、あるいは読み込みだけで書き込みができない、
あるいは一部の機能しか使えないなどに関しての資料が見当たらないので一概に30以上というのは不適切かも知れません。
次によく使われるファイルシステムを取り上げて説明してみましょう。
ファイルシステム
ここでは下位レイヤでのファイルシステムを個別に説明します。
ext2 ファイルシステム
ext2ファイルシステム [7] は正式名称Second Extented Filesystemといい、ext2fs とも書きます。Linuxのために開発されたファイルシステムです。前身である Ext ファイルシステムの次のバージョンと位置づけられます。最大ファイルシ ステムサイズ4TB、最大ファイルサイズ2GB まで扱えます。
ext2ファイルシステムはファイルの読み書きで良い局所性を出すための工夫が
されています。書き出しが行われる時、同じブロックグループ内で、隣接する
8ブロックを先行して割り当てするので、連続しての書き込みの効率があがり
ます。このような書き方をするので当然、連続しての読み込みをする際のヒッ
ト率が高くなります。
ext3 ファイルシステム
ext3 [8] ext2をベースにジャーナリングファイルシステム(Journaling Filesystem)に 拡張したものです。ジャーナリングファイルシステムとはメタデータと呼ばれ るファイル属性などの変更履歴をジャーナルログに記録しておき、ファイルシ ステムの整合をチェックする時は、そのジャーナルを使う方式です。ext2ファ イルシステムのように整合性をチェックするためにファイルシステム全部を走 査する必要がないので高速に処理ができます。最大ファイルシステムサイズ 4TB、最大ファイルサイズ4TBまで扱えます。
JFS / ReiserFS / XFS
ext3と比べるべきファイルシステムとしてIBM社が開発したJFSファイルシステム [9] 、 ReiserFS ファイルシステム、 あるいはシリコングラフィックス社が開発したXFSファイルシステム [10] などもあります。 これらはいずれもジャーナリング機能を持っており、かつ、色々な特色ある機能を持っています。
JFS は IBM の AIX、 XFS はシリコングラフィックス社の IRIX といった実績のあるUNIX系OSで使われていたものであり、 それがLinuxに移植され利用されるに至っています。 JFSにしてもXFSにしても、これらの能力を最大限に生かしきるのはサーバやクラスタといったエンタプライス環境であり、 また熟練したオペレーターによる運用によって始めて能力や特性をいかせることができるといっても過言ではありません。 それらを熟知した上で利用することをお薦めします。
- 補足
- 日常利用するディスクトップのレベルであれば、GNU/Linuxのディストリビューションがデフォルトで選択するファイルシステムで十分な能力を発揮します。
ext4 / Reiser4 / NILFS2 / Btrfs
JFSやXFSやReiserFSの次の世代のファイルシステムです。
- ext4 : ext3の後継
- Reiser4 : ReiserFSの後継。まったくの別実装。
- NILFS2 : Log-structured ファイルシステム、耐故障性の向上、スナップショット機能
- Btrfs : 耐故障性の向上、多機能
(TBD)
ISO9660 ファイルシステム
CDROMの規格であるISO9660のファイルシステムです。このファイルシステムを 指定してマウントすると、CDROM (もちろんISO9660であること) をリードオン リーのファイルシステムと認識されます。類似のファイルシステムにJPLIETファ イルシステムやZISOFSファイルシステム、DVD用のUDFなどもなどもあります。
tmpfs、ramfsファイルシステム
メモリ上に展開するファイルシステムです。メモリ上にあるのでシステムが停止すればなくなります。一時的なファイルを作成するファイルシステムとして利用されます。
- 調べてみよう
- dfやmountコマンドを使って、自分のファイルシステムでtmpfsがどのように使われているか調べてみよう。
その他にもLiveCDのようにハードディスクを使えないような場合に、メモリ上にファイルシステムを構築する際に利用されます。
- 補足
- ramfsは物理的メモリしか使わないのに対し、tmpfsは仮想記憶上に取られます。つまりtmpfsは、システムの物理的記憶空間が足りなくなってきた場合、内容をスワップします。そのため、搭載している物理的メモリよりも大きなエリアを取ることも可能です。
ネットワークファイルシステム
NFS
NFS (Network filesystem) はUnixで最初に使われたネットワークを経由して ファイルシステムをマウントする仕組みです。NFSの仕様はUNIXだけではなく 抽象化したファイルシステムとなっています。たとえば異なるUnixの種類同士 (例えばFreeBSDのファイルシステムとLinuxとか、あるいはSUN Solarisと SystemV IIIとか)、あるいはUnixとWindowsといったファイルシステムの種類 の異なるものでもネットワークを介して共有することができます。LANで接続 されたコンピュータ間でファイルを共有することを想定しています。
CODA
CODA [11] は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になります。
脚注
- ↑ Filesystem Hierarchy Standard, FHS 2.3 was released January 29, 2004. http://refspecs.linuxfoundation.org/fhs.shtml
- ↑ http://lxr.linux.no/source/include/linux/dirent.h?v=2.6.8.1
- ↑ http://lxr.linux.no/source/include/linux/fs.h?v=2.6.8.1
- ↑ VFSに関する資料 http://www.valinux.co.jp/docs/pdf/D-2.pdf
- ↑ Jim Mauro and Richard McDougall, "Solaris Internals: Core Kernel Components", Prentice Hall Professional, 2001
- ↑ http://lxr.linux.no/#linux+v2.6.36/fs/
- ↑ ext2に関する資料 http://www.linux.or.jp/JF/JFdocs/Filesystems-HOWTO-6.html
- ↑ ext3に関する資料 http://www.valinux.co.jp/docs/pdf/D-3.pdf
- ↑ JFS概説 ジャーナル・ファイル・システムによるシステム再始動時間の短縮 http://www.ibm.com/developerworks/jp/linux/library/l-jfs.html
- ↑ http://xfs.org/index.php/Main_Page
- ↑ CODAのウェブサイト http://www.coda.cs.cmu.edu/
目次へ