gitでシンボリックリンクを除外することはできないのかなあと思うことがあるのだが,シンボリックリンクは対象ファイルへのパスを書いたファイルみたいなものらしいということを知って,inodeとかdentryについて調べたときのメモ.

inode

Linuxではファイルはディレクトリに整然と並んでいるが,ディスク上やSSD上でもディレクトリの構造を反映してファイルが格納されているわけではない.ディレクトリ上でファイルを移動したとき,その実体のディスク上での位置は依然としてそのままである.

Linuxではinodeと呼ばれる構造体によって,以下の情報を管理している.

  • ファイルの種類
  • UIDとGID
  • パーミッション
  • バイト単位のファイルサイズ
  • このファイルに割り当てたブロック数
  • データブロックへのポインタ(ファイルの中身が書き込まれている)

詳細

SSDやHDDがどのように管理されているかについての詳細.ディスクの先頭には「ブートブロック」があり,その次に「スーパーブロック」がある.これは

  • i-nodeテーブルのサイズ
  • 論理ブロック数
  • 論理ブロックサイズ

などの情報を保持している.i-nodeの個数の上限は決め打ちされており,

$ df -i

で確認できる(いくらデバイスに空きがあっても,これ以上の個数のファイルとディレクトリは作成できない).

その次にi-nodeテーブルの実体と,データブロックが続く.inode番号はinodesテーブルのエントリーの主キーであり,スーバーブロックのサイズなどもハードコードされているため,任意の番号のinodeのディスク上での位置を直接求められる(?).

dentry

Linuxにおけるディレクトリは以下のような情報などを格納した dentry という構造体である.

  • struct inode* d_inode このdentryのinodeエントリーへのポインター
  • struct qstr このディレクトリの名前(多分1回層だけ?)
  • struct list_head d_subdirs サブディレクトリdentryのリストへのポインター
  • struct dentry* d_parent 親ディレクトリのdentryへのポインター

例として / のinodeを0として, /home/hoge/Download/dl.png のinodeを解決してみる.

  1. まず / のinodeは0だから inodes[0] を参照する.そこには / のブロックへのポインターがあり,それを参照すると / のdentryを得る.
  2. その中のサブディレクトリのリストのポインターを得る.
  3. その中に名前が"home"のものがあるか探す.見つかったら(それはdentryへのポインタなので)そのinodeを参照する.そこには /home/ のブロックへのポインターがあるから,それを参照すると /home/ のdentryを得る.
  4. その中のサブディレクトリのリストのポインターを得る.
  5. その中に名前が"hoge"のものがあるか探す.見つかったらその(それはdentryへのポインタなので)そのinodeを参照する.そこには /home/hoge/ のブロックへのポインターがあるから,それを参照すると /home/hoge/ のdentryを得る.
  6. その中のサブディレクトリのリストのポインターを得る.
  7. その中に名前が"Download"のものがあるか探す.見つかったらその(それはdentryへのポインタなので)そのinodeをを参照する.そこには /home/hoge/Download のブロックへのポインターがあるから,それを参照すると /home/hoge/Download のdentryを得る.
  8. dl.png が見つかる.

おそらくこういった感じで解決が可能だと思う(?).

ハードリンク

ハードリンクはあるinode番号を持つリソースに,別名のファイル名を持たせたdentryである.

ln original.txt alias.txt

これはoriginal.txtのハードリンクalias.txtを作成したことになるが,alias.txtoriginal.txtと同一のinode番号を持っている.

rmコマンドの意味

inodeは参照カウントを持っている.そしてあるファイルをrmすると対応するinode番号のinodeの参照カウントがデクリメントされる.上の例では

rm original.txt

してもまだalias.txtは残っているし,もちろんディスク上の実体も残っている.このようにrmコマンドはディレクトリエントリーを消去するだけであり,ディスク上の実体は消去しない.そのため使用中のファイルも(形式上)rmできる.inodeを参照するプロセスがなくなるまでファイルの実体の消去は遅延される.

遅延書き込み

dirtyリストの管理とかLRUとか.

リンク1