Unix系OSのハードリンクとシンボリックリンクの違いとは?inode・削除時の挙動・別ファイルシステムへのリンクを解説

Unix系

Unix系OSでは、1つのファイルへ別の名前からアクセスする仕組みとして「ハードリンク」と「シンボリックリンク」があります。見た目上はどちらも別名から同じ内容へアクセスできるため似ていますが、ファイルシステム内部ではまったく異なる仕組みで実現されています。

特に重要なのは、ハードリンクは同じinodeを参照する別のディレクトリエントリであり、シンボリックリンクは対象へのパス文字列を保持する独立したファイルだという点です。この違いによって、元の名前を削除したときの挙動や、別のファイルシステムへリンクを作れるかどうかが変わります。

この記事では、inodeとディレクトリエントリの関係から、ハードリンクとシンボリックリンクの内部構造、削除時の挙動、ファイルシステムをまたぐ場合の制約、実際のコマンド例まで順番に解説します。

Unix系ファイルシステムでは「ファイル名」と「ファイル本体」は別に管理される

ハードリンクとシンボリックリンクを理解するには、まずUnix系ファイルシステムでファイル名とファイル本体がどのように管理されているかを知ると分かりやすくなります。

ext4など代表的なUnix系ファイルシステムでは、ファイルのメタデータやデータブロックへの参照はinodeと呼ばれる構造で管理されます。一方、ディレクトリには「ファイル名」と「inode番号」の対応関係が保存されています。

つまり、ファイル名そのものがデータ本体を持っているわけではありません。ディレクトリ内の名前からinodeを探し、そのinodeを通じて実際のデータへアクセスします。

ハードリンクは同じinodeを指す別のファイル名

ハードリンクを作成すると、新しいファイルそのものが複製されるわけではありません。新しいディレクトリエントリが追加され、その名前が元ファイルと同じinode番号を指すようになります。

例えば次のようにします。

echo hello > original.txt
ln original.txt hardlink.txt
ls -li original.txt hardlink.txt

すると、original.txtとhardlink.txtには通常同じinode番号が表示されます。つまり、2つの名前は別々に見えても、実体としては同じinodeと同じデータブロックを参照しています。

ハードリンクには「元ファイル」と「リンク先」という優先関係はありません。どちらも同じinodeを指す対等な名前です。

ハードリンクでは片方を削除してもデータは残る

Unix系OSでファイルを削除する操作は、基本的にはそのファイル名に対応するディレクトリエントリを削除する操作です。ハードリンクが複数ある場合、そのうち1つの名前を削除してもinode自体は残ります。

例えばoriginal.txtとhardlink.txtが同じinodeを参照している状態で、original.txtを削除してもhardlink.txtから内容を読み続けることができます。

rm original.txt
cat hardlink.txt

この場合でも「hello」と表示されます。inodeが保持するリンク数が1つ減るだけで、まだhardlink.txtから参照されているためデータは解放されません。

ハードリンクのリンク数が0になったときにファイルは削除対象になる

inodeには、そのinodeを参照しているハードリンク数が記録されています。ls -lで表示される数値の一つがリンク数です。

すべてのハードリンクを削除するとリンク数が0になります。さらに、そのファイルを開いているプロセスも存在しなくなった段階で、inodeとデータブロックはファイルシステムから解放されます。

この仕組みのため、Unixでは実行中のプログラムやログファイルをrmで削除しても、プロセスがそのファイルを開いたままなら、しばらくデータがディスク上に残ることがあります。

シンボリックリンクは対象パスを保存した独立したファイル

シンボリックリンクはハードリンクとは異なり、対象ファイルと同じinodeを共有しません。シンボリックリンク自身が独立したinodeを持ち、その内容としてリンク先のパス文字列を保存します。

例えば次のように作成します。

ln -s original.txt symlink.txt
ls -li original.txt symlink.txt

この場合、original.txtとsymlink.txtでは通常inode番号が異なります。symlink.txtには「original.txt」というパス情報が保存されています。

アプリケーションがsymlink.txtを開こうとすると、カーネルはまずシンボリックリンクを読み、その中に保存されたパスをたどって本来のファイルへアクセスします。

元ファイルを削除するとシンボリックリンクは壊れる

シンボリックリンクは対象ファイルのinodeそのものではなく、名前やパスを記録しているだけです。そのため、リンク先のファイルを削除するとシンボリックリンク自体は残りますが、その先へアクセスできなくなります。

例えば次の状態を考えます。

ln -s original.txt symlink.txt
rm original.txt
cat symlink.txt

すると通常は「No such file or directory」のようなエラーになります。symlink.txt自体は存在していますが、参照しているoriginal.txtというパスがなくなっているためです。

このような状態は「壊れたシンボリックリンク」や「dangling symlink」と呼ばれます。

同じ名前のファイルを再作成するとシンボリックリンクは再び有効になる

シンボリックリンクはinodeではなくパスを参照しているため、リンク先を削除した後でも、同じ場所に同じ名前のファイルを再作成すると再びアクセスできるようになります。

例えばoriginal.txtを削除した後に、新しいoriginal.txtを作成すると、symlink.txtはその新しいファイルを指します。

echo new > original.txt
cat symlink.txt

この場合は「new」と表示されます。以前のoriginal.txtと新しいoriginal.txtはinodeが異なる可能性がありますが、シンボリックリンクはパスだけを見ているため問題ありません。

ハードリンクは基本的に別ファイルシステムへ作れない

ハードリンクには重要な制約があります。原則として、異なるファイルシステムをまたいで作成することはできません。

理由は、ハードリンクが「同じファイルシステム内のinode番号を指すディレクトリエントリ」だからです。inode番号の意味はそのファイルシステム内でのみ有効であり、別のファイルシステムのinodeを直接参照する仕組みにはなっていません。

例えば/homeが1つのファイルシステム、/mnt/dataが別のファイルシステムだった場合、次の操作は失敗します。

ln /home/user/file.txt /mnt/data/file.txt

多くの環境では「Invalid cross-device link」のようなエラーになります。

シンボリックリンクは別ファイルシステムにも作れる

シンボリックリンクはinodeを直接参照せず、単にパス文字列を保存しているため、ファイルシステムの境界をまたぐことができます。

例えば/homeと/mnt/dataが別ファイルシステムでも、次のように作成できます。

ln -s /home/user/file.txt /mnt/data/file.txt

/mnt/data/file.txtというシンボリックリンクには「/home/user/file.txt」というパスが保存されるため、対象が別デバイスや別マウントポイントに存在していても問題ありません。

ネットワークファイルシステムや別パーティション上のファイルを参照するときにも、シンボリックリンクが使われる理由の一つです。

ハードリンクは通常ディレクトリには作れない

一般ユーザーは通常、ディレクトリに対するハードリンクを作成できません。ディレクトリのハードリンクを自由に作れると、ディレクトリ構造に循環が生じ、ファイルシステムの走査や整合性管理が複雑になるためです。

なお「.」や「..」など、ファイルシステム内部ではディレクトリ構造を表現するためのリンク的な仕組みが存在しますが、通常のlnコマンドで一般ユーザーが任意のディレクトリへハードリンクを作ることは制限されています。

一方、シンボリックリンクであればディレクトリにも自由に作成できます。

ln -s /var/log logs

この場合、logsへ移動すると実際には/var/logへアクセスできます。

相対パスと絶対パスでシンボリックリンクの挙動が変わる

シンボリックリンクには絶対パスまたは相対パスを保存できます。どちらを使うかによって、ファイルやディレクトリを移動した場合の挙動が変わります。

例えば次のような絶対パスのリンクでは、常に/home/user/file.txtを参照します。

ln -s /home/user/file.txt link.txt

一方、次のように相対パスを指定すると、シンボリックリンク自身が置かれているディレクトリを基準として解決されます。

ln -s ../data/file.txt link.txt

ディレクトリ一式を別の場所へ移動する可能性がある場合は、相対リンクのほうが構成を維持しやすいことがあります。

ハードリンクとシンボリックリンクの違いを表で比較

項目 ハードリンク シンボリックリンク
参照対象 同じinode パス文字列
inode 元の名前と共有 リンク自身が別inodeを持つ
元ファイル削除後 他のリンクから引き続き利用可能 リンク切れになる
別ファイルシステム 原則不可 可能
ディレクトリへのリンク 通常不可 可能
リンク先の存在 作成時に必要 存在しなくても作成可能
見分け方 通常のファイルとほぼ同じ ls -lで「l」とリンク先が表示される

この表の中でも特に重要なのが、ハードリンクはinode共有、シンボリックリンクはパス参照という違いです。その他の挙動のほとんどは、この基本構造から説明できます。

実際にinode番号を確認すると違いが分かりやすい

Linuxなどではlsコマンドの-iオプションでinode番号を確認できます。

echo test > original.txt
ln original.txt hard.txt
ln -s original.txt soft.txt
ls -li original.txt hard.txt soft.txt

original.txtとhard.txtは同じinode番号になりますが、soft.txtだけは異なるinode番号になります。

さらにls -lを使うと、シンボリックリンクは次のように「->」でリンク先が表示されます。

soft.txt -> original.txt

ハードリンクにはこの表示がないため、ファイル名だけを見ると通常のファイルとほとんど区別できません。

バックアップや容量計算でもハードリンクの性質が影響する

ハードリンクされた複数のファイル名は同じデータブロックを共有するため、ファイルサイズを単純に合計すると実際のディスク使用量より大きく見える場合があります。

例えば1GBのファイルに10個のハードリンクを作っても、データ本体が10GBになるわけではありません。ディレクトリエントリは増えますが、1GBのデータブロックは共有されています。

そのため、バックアップソフトやコピーコマンドがハードリンク関係を保持するかどうかによって、バックアップ先の使用量が変わることがあります。単純コピーではそれぞれ独立したファイルとして複製され、容量が増える場合があります。

シンボリックリンクをコピーするときはツールのオプションに注意

シンボリックリンクをコピーする場合、ツールによって「リンクそのものをコピーする」のか「リンク先の実ファイルをコピーする」のかが異なることがあります。

例えばcpには、シンボリックリンクをたどるかどうかに関係する複数のオプションがあります。バックアップやディレクトリ移行をするときは、リンクを維持したいのか実体をコピーしたいのかを明確にする必要があります。

特にリンク先が大量のデータを持つ場合、意図せずシンボリックリンクを追跡するとコピー量が大幅に増えることがあります。

どちらを使うべきかは用途で決まる

同じ実体に複数の正式なファイル名を与えたい場合や、片方の名前を削除してもデータを保持したい場合にはハードリンクが適しています。ただし、同一ファイルシステム内という制約があります。

一方、別ディレクトリや別ファイルシステム上のファイルを参照したい場合、ディレクトリへリンクしたい場合、リンク先を分かりやすく表現したい場合にはシンボリックリンクが便利です。

実際のUnix系OSではシンボリックリンクのほうが柔軟で扱いやすいため、設定ファイルや共有ディレクトリの参照など幅広い用途で利用されています。

まとめ|ハードリンクはinode共有、シンボリックリンクはパス参照

Unix系OSにおけるハードリンクとシンボリックリンクの本質的な違いは、何を参照しているかにあります。ハードリンクは同じinodeを指す別のディレクトリエントリで、シンボリックリンクはリンク先のパスを保持する独立したファイルです。

そのため、元の名前を削除してもハードリンクが残っていればデータは利用できますが、シンボリックリンクでは対象パスが消えるとリンク切れになります。また、ハードリンクは原則として別ファイルシステムへ作れませんが、シンボリックリンクはパスを保存するだけなのでファイルシステムをまたいで作成できます。

「同じinodeを共有するのがハードリンク」「別inodeを持ち、パスを保存するのがシンボリックリンク」と覚えておけば、削除時の挙動、ファイルシステム境界、ディレクトリへのリンク可否など、多くの違いを一貫して理解できます。

コメント

タイトルとURLをコピーしました