haraduka's diary

やる気が欲しい

リンクとかマウントとかコンテナとか

mountとかlinkのあたりの話がだんだんとごっちゃになってきてしまったので一回まとめます。

ファイルシステム
ファイルシステムっていうのはディレクトリがあって、そこにディレクトリエントリと呼ばれるファイルなどの情報があります。ディレクトリエントリからファイルのinodeにアクセスして、その先のファイルの実体にアクセスします。


ハードリンクとシンボリックリンク
これらリンクは結局は、別名でアクセスできるよ〜というものです。ハードリンクは別々のディレクトリエントリが同じinodeを参照することでこの別名アクセスを実現しています。つまり、dentry -> inode -> 実体 という構成の中で、inodeは共通でdentryのみがことなっているのです。これは

$ echo "nyan" > test1
$ ln test1 test2 //シンボリックリンクなら -s をつける
$ ln -li test1 test2

とやってinodeの値が一緒になることで確認できます。inodeはファイルシステムごとに違うため、別々のファイルシステム間でハードリンクを作ることはできません。また、基本的にはファイルに関するハードリンクしかできなく、ディレクトリは微妙っぽいです。また、ハードリンクはinodeを参照しているため元のファイルを移動しても全然大丈夫で、元のファイルを削除しても作成したハードリンクは壊れません。これは、inodeがいくつのエントリから参照されているかを管理していて、それが0になったらファイルが削除されるからです。

シンボリックリンクはパス、つまり/home/hogeとかを参照することで別々アクセスを実現しています。パスで参照するため、別々のファイルシステムでも大丈夫であり、ディレクトリに対しても適用することが可能です。パスで指定するため、実体は一緒ですがinodeは異なっています。これはハードリンクの項と同じように確認できます。パスで指定することによるデメリットとして、元のファイルの場所が移動するとシンボリックリンクは壊れてしまいます。元のファイルを削除するとシンボリックリンクは残りますが、壊れて使えません。

こんな感じですが、アーカイブにするときも注意が必要で、tarなら基本的にハードリンクもシンボリックリンクも考慮してくれ、元のファイルを含まずシンボリックリンクだけのときでも -h オプションで実体を取り込んでくれるそうです。zipはハードリンクは考慮してくれないそうです。

mount - bind mount
mountとは一般に、外部デバイスをOSに認識させて使えるようにする行為だが、bind mountというとても便利なものもあります。bind mountはディレクトリをディレクトリにmountすることが可能です。簡単に言うと、シンボリックリンクの強いバージョンです。なぜシンボリックリンクより強いかというと、例えばchroot環境での作業が挙げられます。chrootとはファイルシステムのルートを変えることによって外部にアクセスできないように安全に作業を行ったりするときに使いますが、シンボリックリンクはパス指定なため当然外部へのアクセスができなくなってしまいます。それに対して、bind mountはディレクトリエントリ下で実現しているためできるそうです。bind mountは所詮mount --bindというmountのオプションなので、/etc/fstabに記述することが可能です。/homeと/varだけは外付けのHDDに格納しよう、とか、一旦ファイルをコピーして書き換えてbind mountしてテスト、とかが使い道っぽいです。

コンテナ
chrootが挙がりましたが、他にもdockerとかlxcとかありますよね。chrootは基本的に他のディレクトリの部分に侵食されないように制限をかけるものですが、lxcはさらに隔離します。その技術がcgroupとnamespaceで、cgroupはcpuやmemoryなどの物理的なリソースを隔離するための機能、namespaceはOSが使用するリソースであるネットワークスタックやPIDを隔離するための機能です。それに対してdockerはlxcにバージョン管理や自動ビルドなどの機能を追加したエコシステムだそうです。