ファイルシステム
ファイルシステムの構造
ここでのファイルシステムは、ファイルを管理するシステム全体のことをいっています。一方、ext2やext3といった下位レベルのレイヤのファイルシステムも同じファイルシステムと呼ぶが一般的です。 これは古典的なUNIXでは、1つのファイルシステムは下位レイヤレベルで1つの形式しか持っていなかったため問題はありませんでした。 ところが現在では下位レイヤにいろいろな種類のファイルシステムをもっています。 ですから、前後の文脈を理解しておかないとファイルシステムと全体を意味するファイルシステムと、下位レイヤのファイルシステムをうまく用語で区別できない状況にありますし、文中でもそうなり読んでいて混乱しやすいので注意してください。
ツリー構造
Unixのファイルシステムは/を頂点にしたツリー構造です。Windows系のオペレーティングシステムでは 「C: (Cドライブ)」 といったようにハードウェアである「ドライブ」を意識した構造になっていますが、Unixでは「/」を頂点にしたツリー構造になっています。ディレクトリとはパソコンで言う所のフォルダです。ディレクトリがファイルの属性情報を知っています。ファイル自体はデータのみ入っています。UNIXにおいてのファイルは先頭から連続したバイト列になっています。この事に関して、私達の身の回りにあるコンピュータでは何の不思議もありませんが、むかしの大型汎用機のファイル構成はこのようになっていませんでした。UNIXが登場した当時としては、このような形式はUNIXの特徴でもあったのですが、今やあたりまえになってしまっています。
まずは 「/ (ROOTと呼びます)」にどんなファイルやディレクトリがあるかコマンド 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:といったドライブ名で出てくるのでハードウェアを意識する構造になっていますが、UNIXはハードウェアとしてのハードディスクは意識しません。
- 調べてみよう
- Linuxの標準的ファイルシステム階層のスペック(Filesystem Hierarchy Standard)はLinuxファンデーションがドキュメント化しています。[1]
- 主要なディレクトリの意味
- /bin : システムに最小限必要なコマンド群
- /dev : デバイススペシャルファイル群
- /home : 一般ユーザのディレクトリ
- /lost+found : 破損したファイルの断片を退逃させる (これはファイルシステムが作成するものでLinuxのファイルシステム階層には含まれない)
- /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/sda1 487634 261696 196242 58% /boot /dev/sda2 201820928 11906896 179647588 7% /
/dev/sda1はSATA(Serial ATA)インタフェースで接続され認識された最初のハードディスクの最初のパーティションのことです。sda2は2番目のパーティションを意味しています。 元々/dev/sd? (?はアルファベット1文字が入る)はSCSIインタフェースのためのブロックデバイス名でしたが、現在ではSCSIだけではなく、SATA(Serial ATA)インタフェース、あるいは同等なインタフェースで接続された場合/dev/sd?に割り当てられます。 例えばUSBメモリを使うときも/dev/sd?となります。下の例はUSBメモリを挿した時の状態です。このUSBメモリには HIRONOBU と名前を設定しています。 多くのディストリビューションのデフォルトでは /media/ユーザ名 の下に自動的にマウントします。
/dev/sdg1 3804348 375556 3215828 11% /media/hironobu/HIRONOBU
Linuxでハードディスクに利用できるファイルシステムの種類にはext2、ext3、ext4、 JFS、XFS、ReiserFSなど色々な種類が使えます。 近年のディストリビューションではデフォルトのファイルシステムがext4というものが多いですが、 これらのファイルシステムは、それぞれ性能や機能に特徴があります。 ユーザの選択肢が広く、その選択をユーザにゆだねているのもまたLinuxの特徴です。 個々のファイルシステムの特徴に関しては後ほど説明します。
- 調べてみよう
- Linux以前のUnixも一つのオペレーティングシステムは主たるファイルシステムは1つだけでした。それは何故でしょう。
ファイルシステムの構築とマウントは非常に簡単です。ハードディスクを指定してフォーマットし、それとマウントポイントとなるディレクトリへマウントするだけです。
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] [5] が用意されているからです。
VFSは個々のファイルシステムとユーザの間のクッションの役目を果たしており、
ユーザ側からはVFSしか見えないようになっています。
このVFSがファイルシステム間の違いを吸収し、統一したインタフェースをユーザ側に提供します。
むかしむかしのUNIXはディレクトリとファイルのアクセスの違いはありませんでした。
ディレクトリはシステムがファイルを管理するための内容を持ったファイルでしかありませんでした。
ファイルシステムが1種類しかなく自分のマシンに接続するハードディスク上にあった頃は、
これでも十分ですが、複数のファイルシステムが存在する場合はそうもいきません。
機能や仕様が個々に違う、すべてのファイルシステムに同じ方法でアクセスすることを提供しなければいけません。
ファイルシステムの上に仮想的なファイルシステムを加えて統一したインタフェースを提供するようになったのは1984年のSUN MicrosystemsがSunOS 2.0が最初です。[6]
色々なファイルシステムを扱えるフレームワークは、Sunが開発した NFS(Network File System) が別のマシン上にあるファイルシステムをネットワーク経由でマウントするために必要でした。
VFSの下に位置するファイルシステムは、少なくともカーネルのソースコードで数えた所、50以上ありました。
[7]
個々のファイルシステムがどこまで利用可能なのか、つまり、常用のファイルシステムとして使えるのか、
互換性のために残しているのか、あるいは読み込みだけで書き込みができない、
あるいは一部の機能しか使えないなどに関しての資料が見当たらないので一概に50以上というのは不適切かも知れません。
しかし、数種類、あるいは十数種類というレベルではないことは確かです。
次に主要なファイルシステムを取り上げて説明します。
ファイルシステム
ここでは下位レイヤでのファイルシステムを個別に説明します。
その前に、現在利用しているGNU/Linuxのシステムがどのようなファイルシステムをサポートしているのかを確認する時は /proc/filesystems を参照するとわかります。
% cat /proc/filesystems
ext2 ファイルシステム
ext2ファイルシステム [8] は正式名称Second Extented Filesystemといい、ext2fs とも書きます。Linux のために開発されたファイルシステムです。 前身である Ext ファイルシステムの次のバージョンと位置づけられます。 現在も /boot のファイルシステムは ext2 ファイルシステムを利用しているディストリビューションが多くあります。 最大ファイルシステムサイズ4TB (カーネル2.6からは32TB)、最大ファイルサイズ2GB まで扱えます。
ext2ファイルシステムはファイルの読み書きで良い局所性を出すための工夫がされています。 書き出しが行われる時、同じブロックグループ内で、隣接する8ブロックを先行して割り当てするので、連続しての書き込みの効率があがります。 このような書き方をするので当然、連続しての読み込みをする際のヒット率が高くなります。
ext3 ファイルシステム
ext3 [9] ext2 をベースにジャーナリングファイルシステム(Journaling Filesystem)に拡張したものです。 ジャーナリングファイルシステムとはメタデータと呼ばれるファイル属性などの変更履歴をジャーナルログに記録しておき、ファイルシステムの整合をチェックする時は、そのジャーナルを使う方式です。 ext2 ファイルシステムのように整合性をチェックするためにファイルシステム全部を走査する必要がないので高速に処理ができます。 最大ファイルシステムサイズ4TB、最大ファイルサイズ4TBまで扱えます。
ext4 ファイルシステム
ext4 は ext3 の後継として作られたファイルシステムです。カーネル2.6.19 から正式採用しています。ext4 のファイルシステムは1EB、ファイルサイズは16TBのサイズをサポートしています。
同時期に存在していた競合していたJFSやXFSファイルシステムから良い点を導入しするなど新しい機能や拡張を行い、また安定性も十分に備え、ext3に比べて大きく進化しています。
たとえばパフォーマンスに関してはブロックの遅延アロケーションが可能になりました。これはなるべくディスク上の物理ブロックを連続に確保するために書き込みを遅滞させます。連続した物理ブロックに書き込むことが出来るようになり、その後にファイルをリードする際に高速に読み込むことが出来るようになります。ファイルサイズが最初にわかっている場合はファイルのプリアロケーションの機能を使いディスク上の物理ブロックを予め確保することが出来ます。
他にもたくさんの新しい機能があります。調べるには下記の資料が役に立つでしょう。
- RED HAT ENTERPRISE LINUX ストレージ管理ガイド 第6章 EXT4 ファイルシステム
- AAnatomy of ext4 Anatomy of ext4
JFS / ReiserFS / XFS
ext4と比べるべきファイルシステムとして過去IBM社が開発しLinuxカーネルにマージされているJFSファイルシステム [10] 、 ReiserFS ファイルシステム、 あるいは過去シリコングラフィックス社が開発しLinuxカーネルにマージされているXFSファイルシステム [11] などもあります。 これらはいずれもジャーナリング機能を持っており、かつ、特色ある機能を持っています。
JFS は IBM の AIX、 XFS はシリコングラフィックス社の IRIX といった実績のあるUNIX系OSで使われていたものであり、 それが Linux に移植され利用されるに至っています。 JFS にしても XFS にしても、これらの能力を最大限に生かしきるのはサーバやクラスタといったエンタープライズ環境であり、 熟練オペレーターによる運用が行われる場合、これらのエンタープライズ環境で必須な障害からの復帰などの能力や特性を十分に活かすことが出来るでしょう。
- 補足
- 日常利用するディスクトップのレベルであれば、GNU/Linuxのディストリビューショ
Reiser4 / NILFS2 / Btrfs
JFSやXFSやReiserFSの次の世代のファイルシステムです。
- Reiser4 : ReiserFSの後継。まったくの別実装。
- NILFS2 : Log-structured ファイルシステム、耐故障性の向上、スナップショット機能
- Btrfs : 耐故障性の向上、多機能
(TBD)
ISO9660 ファイルシステム
CDROMの規格であるISO9660のファイルシステムです。このファイルシステムを 指定してマウントすると、CDROM (もちろんISO9660であること) をリードオン リーのファイルシステムと認識されます。類似のファイルシステムにJPLIETファ イルシステムやZISOFSファイルシステム、DVD用のUDFなどもなどもあります。
tmpfs、ramfsファイルシステム
メモリ上に展開するファイルシステムです。メモリ上にあるのでシステムが停止すればなくなります。一時的なファイルを作成するファイルシステムとして利用されます。tmpfsは仮想記憶上に取られるので利用するシステムの記憶領域が足りない時はページイン・ページアウトが発生します。
- 調べてみよう
- dfやmountコマンドを使って、自分のファイルシステムでtmpfsがどのように使われているか調べてみよう。
その他にもLiveCDのようにハードディスクを使えないような場合に、メモリ上にファイルシステムを構築する際に利用されます。
- 補足
- ramfsは物理的メモリしか使わないのに対し、tmpfsは仮想記憶上に取られます。つまりtmpfsは、システムの物理的記憶空間が足りなくなってきた場合、内容をスワップします。そのため、搭載している物理的メモリよりも大きなエリアを取ることも可能です。
JFFS / JFFS2
USBストレージやSDカードなどフラッシュメモリを使った記憶装置をファイルシステムとして使うためのフラッシュ・ファイルシステムがLinuxには用意されています [12] 。 フラッシュ・ファイルシステムとして JFFS (Journaling Flash File System)、 JFFS2 (Journaling Flash File System 2)、 YAFFS2 (Yet Another Flash File System 2) などがあります。 JFFSは現在では使われておらず、後継のJFFS2が利用されています。
フラッシュメモリ(ここではUSBストレージやSDカードに使われているNAND フラッシュ・デバイスとします)には書き込みや読み込みはハードディスクと違う動作を必要としますし、またフラッシュメモリには書き換え上限があり同じ場所で書き込みを繰り返し上限に達すると、その場所が書き込めなくなるります。そのためフラッシュメモリに特化したファイルシステムが用意されています。
一方で近年ではSDカードやUSBストレージのハードウェアも進化し特別なファイルシステムがなくとも効率よく、かつ寿命が伸びる仕組みを取り入れているのでSDカードやUSBストレージを使っているからといって必ずJFFS2のようなファイルシステムが必要であるというわけではない状況になって来ています。たとえばAndroidの場合、古くはJFFS2でしたが後にext4に切り替えています。
ネットワークファイルシステム
NFS
NFS (Network filesystem) はUnixで最初に使われたネットワークを経由してファイルシステムをマウントする仕組みです。 NFSの仕様はUNIXだけではなく抽象化したファイルシステムとなっています。 たとえば異なるUnixの種類同士 (例えばFreeBSDのファイルシステムとLinuxとか、あるいはSUN SolarisとSystemV IIIとか)、 あるいはUnixとWindowsといったファイルシステムの種類の異なるものでもネットワークを介して共有することができます。 LANで接続されたコンピュータ間でファイルを共有することを想定しています。
CODA
CODA [13] は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
- ↑ https://github.com/torvalds/linux/blob/master/include/linux/dirent.h
- ↑ https://github.com/torvalds/linux/blob/master/include/linux/fs.h
- ↑ VFSに関する資料 https://developer.ibm.com/tutorials/l-virtual-filesystem-switch/
- ↑ Overview of the Linux Virtual File System https://www.kernel.org/doc/html/latest/filesystems/vfs.html
- ↑ Jim Mauro and Richard McDougall, "Solaris Internals: Core Kernel Components", Prentice Hall Professional, 2001
- ↑ https://github.com/torvalds/linux/tree/master/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 https://wiki.archlinux.jp/index.php/JFS
- ↑ http://xfs.org/index.php/Main_Page
- ↑ Linux フラッシュ・ファイルシステムの徹底調査 さまざまな選択肢とそのアーキテクチャー https://www.ibm.com/developerworks/jp/linux/library/l-flash-filesystems/index.html
- ↑ CODAのウェブサイト http://www.coda.cs.cmu.edu/
目次へ