Unix 系ファイルシステムでは、ファイル名とファイルの実体は別々に管理されている。この分離を実現するのが inode(アイノード)という仕組みだ。
ファイル名はただのラベル
ファイル名は inode への「参照」にすぎない。実際のファイルデータやメタデータは inode に格納されている。
人間が識別するためのラベル。ディレクトリ内に「ファイル名 → inode 番号」のペアとして保存される
ファイルの実体を管理するデータ構造。ファイルサイズ、パーミッション、所有者、タイムスタンプ、データブロックの位置などを保持する
# inode 番号を確認する ls -i data.txt # 1234567 data.txt # stat でより詳細な情報を表示 stat data.txt # File: data.txt # Size: 1024 Blocks: 8 IO Block: 4096 regular file # Device: 801h/2049d Inode: 1234567 Links: 1 # Access: (0644/-rw-r--r--) Uid: ( 1000/ user) Gid: ( 1000/ user) # Access: 2024-01-15 10:30:00.000000000 +0900 # Modify: 2024-01-15 10:25:00.000000000 +0900 # Change: 2024-01-15 10:25:00.000000000 +0900
inode に格納される情報
inode にはファイル名以外のすべての情報が格納される。
通常ファイル、ディレクトリ、シンボリックリンクなどの種別と、rwx のアクセス権限。
UID(ユーザー ID)と GID(グループ ID)。
atime(最終アクセス時刻)、mtime(最終更新時刻)、ctime(メタデータ変更時刻)の 3 種類。
ファイルの実データがディスク上のどこにあるかを示すポインタ。大きなファイルは間接ポインタを使う。
注意すべきは、inode にはファイル名が含まれないことだ。ファイル名はディレクトリ側が管理している。
ハードリンクの仕組み
inode とファイル名が分離しているおかげで、1 つの inode に複数のファイル名を付けられる。これがハードリンクだ。
# ハードリンクを作成 ln original.txt hardlink.txt # 両方とも同じ inode 番号を持つ ls -i original.txt hardlink.txt # 1234567 original.txt # 1234567 hardlink.txt # リンクカウントが 2 になる stat original.txt | grep Links # Links: 2
import os # Python からも inode 番号を確認できる stat1 = os.stat("original.txt") stat2 = os.stat("hardlink.txt") print(stat1.st_ino) # 1234567 print(stat2.st_ino) # 1234567(同じ) print(stat1.st_ino == stat2.st_ino) # True
ハードリンクは「同じ inode を指す別の名前」であり、コピーではない。どちらの名前でファイルを変更しても、同じ実体が変更される。
シンボリックリンクとの違い
シンボリックリンク(ソフトリンク)は inode の仕組みとは異なる。
同じ inode を直接参照する。元ファイルを削除しても、リンクカウントが 1 以上なら inode は残る
ファイルパス(文字列)を保持する別の inode。元ファイルを削除すると「壊れたリンク」になる
# シンボリックリンクは別の inode を持つ ln -s original.txt symlink.txt ls -i original.txt symlink.txt # 1234567 original.txt # 9876543 symlink.txt(別の inode)
inode 番号でファイルを識別する
ファイル名ではなく inode 番号でファイルを識別するのが Unix の流儀だ。
import os def same_file(path1, path2): """2 つのパスが同じファイルを指すか判定""" stat1 = os.stat(path1) stat2 = os.stat(path2) # デバイス ID と inode 番号の両方が一致すれば同じファイル return (stat1.st_dev, stat1.st_ino) == (stat2.st_dev, stat2.st_ino) # または os.path.samefile を使う print(os.path.samefile("original.txt", "hardlink.txt")) # True
デバイス ID も確認するのは、異なるファイルシステム間では inode 番号が重複する可能性があるためだ。
inode の上限
ファイルシステムには inode 数の上限がある。ディスク容量に余裕があっても、inode を使い切ると新しいファイルを作成できなくなる。
# inode の使用状況を確認 df -i # Filesystem Inodes IUsed IFree IUse% Mounted on # /dev/sda1 6553600 234567 6319033 4% /
小さなファイルを大量に作成するシステム(メールサーバーなど)では、inode 枯渇が問題になることがある。