助け合いフォーラム

LinuC

LinuC Lv1-101(Ver10.0)
問題ID : 15004
問題を開く
ハードリンクとシンボリックリンクそれぞれの説明として正しいものはどれか。(3つ選択)

正解

ハードリンクはコピーに比べてディスク容量を消費しない

ハードリンク先のファイルを編集すると、元ファイルも変更される

シンボリックリンクの元ファイルを削除しても、リンクは残る

解説

Linuxではファイル(ディレクトリはファイルの一種)を「ファイルの実体(データ本体)」と「inode」を使用して管理しています。inodeにはファイルの属性や、「ファイルの実体」にアクセスするためのアドレスなどのメタデータ(格納されているデータそのものに関する情報)が格納されています。

ハードリンクとは、ファイルの実体を直接参照するリンクのことです。同じ実体を参照するハードリンクは同じinode番号を持ち、複数作成してもコピーのようにディスク容量を消費しません。そのため、更新が無いファイルのバックアップ手段としてハードリンクが使用されることもあります。
また、ハードリンク先のファイルの中身を編集すると、元ファイルの中身も同じく変更されます。

シンボリックリンクとは、Windowsでのショートカットのようなもので、元ファイルの場所を指し示すリンクのことです。シンボリックリンクが持っている情報は「元ファイル(ディレクトリ)がどこにあるのか」というパス情報のみです。
シンボリックリンクの元ファイルを削除すると(他に同じinode番号を持つハードリンクが無ければ)、ファイルの実体は削除されますが、リンクは残ります。ただその場合、シンボリックリンクにアクセスすると、リンクしている元ファイルが無いためエラーになります。

したがって正解は
・ハードリンクはコピーに比べてディスク容量を消費しない
・ハードリンク先のファイルを編集すると、元ファイルも変更される
・シンボリックリンクの元ファイルを削除しても、リンクは残る
です。

その他の選択肢については以下のとおりです。

・ハードリンクは異なるファイルシステムに作成できる
inode番号はファイルシステム毎に管理されるため、異なるファイルシステムへハードリンクを作成する事はできません。

・シンボリックリンクの元ファイルとリンクファイルのinode番号は同じである
シンボリックリンクはファイルの実体を指しませんので、inode番号は元ファイルと異なります。

参考

Linuxではファイル(ディレクトリはファイルの一種)を「ファイルの実体(データ本体)」と「inode」を使用して管理しています。inodeにはファイルの属性や、「ファイルの実体」にアクセスするためのアドレスなどが格納されています。
Linuxには、同じ「ファイルの実体」に対して複数の名前でアクセスできる、リンクという仕組みが2種類あります。それが「ハードリンク」と「シンボリックリンク」です。

【ハードリンク】
ハードリンクとは、ファイルの実体を直接参照するリンクのことです。ファイルを新規作成した場合は、ハードリンクが1つある状態です。
同じ実体を参照するハードリンクは同じinode番号を持ち、複数作成してもコピーのようにディスク容量を消費しません。



上図のFile1とFile2は同じ実体を参照しています。ですのでFile1の中身を編集すると、File2の中身も同じく変更されます。

ハードリンクの数とinode番号は「ls -il」コマンドで確認することが出来ます。


ハードリンクを作成するにはlnコマンド(書式:ln 元ファイル リンクファイル)を利用します。
例)File1のハードリンクをFile2として作成する場合


File2はFile1のハードリンクのため、inode番号が同じです。ただこの時点で、どちらがリンクファイルであるかの区別は無くなります。
この状態でFile1を削除しても、File2が実体にリンクしているため実体は残ります(削除されません)。File2も削除し、ハードリンクが0になると、実体がはじめて削除されます。

ハードリンクの制限として以下の2点があります。
1. ディレクトリのハードリンクは作成できない
2. 異なるファイルシステム(パーティション)にハードリンクを作成できない

1の制限は循環ディレクトリの作成を防ぐためです。例えば、testという1ユーザーしか利用しない環境で「/home」を「/home/test」にハードリンクしてしまうと、「/home/test」の「/home」が「/home/test」に置き換えられるため、「/home/test/test/test/...」と無限に続く循環ディレクトリができてしまうことになります。

2の制限はinode番号が各ファイルシステム毎に別々に管理されているためです。異なるファイルシステムではinodeの利用状況が異なるため、全く同じinodeを割り当てて正しく参照できる保証がありません。

これらの制限はシンボリックリンクを使う事で解決できます。

【シンボリックリンク】
シンボリックリンクとは、Windowsでのショートカットのようなもので、元ファイルの場所を指し示すリンクの事です。
シンボリックリンクが持っている情報は「元ファイル(ディレクトリ)がどこにあるのか」というパス情報のみです。



上図のFile2はFile1への単なるショートカットです。
File1を削除すると(他に同じinode番号を持つハードリンクが無ければ)、ファイルの実体は削除されますが、File2は残ります。ただその場合、File2にアクセスすると、リンクしているFile1が無いためエラーになります。

シンボリックリンクを作成するにはlnコマンドに「-s」オプションを付加して作成します。(書式:ln -s 元ファイル リンクファイル)
例)File1のシンボリックリンクをFile2として作成する場合


File1とFile2ではinode番号が違う事が分かります。
また、File2にはシンボリックリンクを示す「l」がパーミッションの先頭に表示されています。ファイル名を示す欄では、File2はFile1のシンボリックであることが分かります。
上に戻る

動的inodeのファイルシステムでもハードリンク作成はディスク容量を消費しないのか?

投稿日 2024/03/20

15004の回答で「ハードリンクはディスク容量を消費しない」が正解とされてますが
ハードリンクを作成した際にはディスク中の固定サイズ領域であるinodeテーブルに情報が
追加(=容量を消費)されていくのであって通常のファイル保存に使う領域が消費されることはない、という理解であってますか?

もしそうだとすると、動的inodeのファイルシステムではその限りではなくなりそうなので
通常のファイル保存に使う領域は、実質inodeのために動的確保された領域のために消費され(または容量の取り分が減らされ)て
しまうのではないですか?
あるいは、動的といっても規定サイズの領域の範囲内で可能な数までは動的生成が可能ということでしょうか?

2024/03/20 14:35

自分の読解力の問題ですみません。質問の内容がよく理解できませんでしたが、こういう検証をしたいがうまくいかないので質問したという意図で良いのでしょうか?

・動的inodeのファイルシステム(例:Btrfs)の準備

# dd if=/dev/zero of=/tmp/btrfs.img bs=1M count=1000
1000+0 records in
1000+0 records out
1048576000 bytes (1.0 GB, 1000 MiB) copied, 2.65423 s, 395 MB/s
# mkfs.btrfs /tmp/btrfs.img
btrfs-progs v5.16.2
See http://btrfs.wiki.kernel.org for more information.

NOTE: several default settings have changed in version 5.15, please make sure
      this does not affect your deployments:
      - DUP for metadata (-m dup)
      - enabled no-holes (-O no-holes)
      - enabled free-space-tree (-R free-space-tree)

Label:              (null)
UUID:               d8471c85-31fe-4aa8-b94c-83c30de9637a
Node size:          16384
Sector size:        4096
Filesystem size:    1000.00MiB
Block group profiles:
  Data:             single            8.00MiB
  Metadata:         DUP              50.00MiB
  System:           DUP               8.00MiB
SSD detected:       no
Zoned device:       no
Incompat features:  extref, skinny-metadata, no-holes
Runtime features:   free-space-tree
Checksum:           crc32c
Number of devices:  1
Devices:
   ID        SIZE  PATH
    1  1000.00MiB  /tmp/btrfs.img

# mount -t btrfs /tmp/btrfs.img /mnt
# mount | grep /mnt
/tmp/btrfs.img on /mnt type btrfs (rw,relatime,ssd,space_cache=v2,subvolid=5,subvol=/)
# df /mnt
Filesystem     1K-blocks  Used Available Use% Mounted on
/dev/loop2       1024000  3616    904192   1% /mnt

・何か元になるファイルを用意する(今回はカーネルイメージ)

# cp /boot/vmlinuz /mnt
# ls /mnt
vmlinuz
# ls -l /mnt
total 11364
-rw------- 1 root root 11634760 Mar 20 14:25 vmlinuz

・ファイルシステムの空き容量を確認する(今回は892828)

# sync
# df /mnt
Filesystem     1K-blocks  Used Available Use% Mounted on
/dev/loop2       1024000 14980    892828   2% /mnt

・ハードリンクを作ってみる(今回はコピーしたカーネルイメージを hardlink というファイルにリンク)

# ln /mnt/vmlinuz /mnt/hardlink
# ls -l /mnt
total 22728
-rw------- 2 root root 11634760 Mar 20 14:25 hardlink
-rw------- 2 root root 11634760 Mar 20 14:25 vmlinuz

・ファイルシステムの空き容量に変化があるか確認する(変化なく892828のまま)

# sync
# df /mnt
Filesystem     1K-blocks  Used Available Use% Mounted on
/dev/loop2       1024000 14980    892828   2% /mnt

・ハードリンクが同じinodeを使用しているかを確認する(どちらも 257)

# stat /mnt/vmlinuz
  File: /mnt/vmlinuz
  Size: 11634760  	Blocks: 22728      IO Block: 4096   regular file
Device: 2eh/46d	Inode: 257         Links: 2
Access: (0600/-rw-------)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2024-03-20 14:25:41.540446902 +0900
Modify: 2024-03-20 14:25:41.556447169 +0900
Change: 2024-03-20 14:26:58.613713062 +0900
 Birth: 2024-03-20 14:25:41.540446902 +0900
# stat /mnt/hardlink
  File: /mnt/hardlink
  Size: 11634760  	Blocks: 22728      IO Block: 4096   regular file
Device: 2eh/46d	Inode: 257         Links: 2
Access: (0600/-rw-------)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2024-03-20 14:25:41.540446902 +0900
Modify: 2024-03-20 14:25:41.556447169 +0900
Change: 2024-03-20 14:26:58.613713062 +0900
 Birth: 2024-03-20 14:25:41.540446902 +0900


コメント

m miki_y

2024/03/24 17:40

ありがとうございます。 いえ、動的inodeのファイルシステムでもハードリンク作成はディスク容量を消費しないといえるのか、またそれはなぜか簡単に理由(しくみ)を教えてほしい、 という意図で質問しました。

a arashi1977

2024/03/24 22:16

意図を補足いただきありがとうございます。 ↑の以下の部分では「動的inodeのファイルシステムでもハードリンク作成はディスク容量を消費しないといえる」ように見えるのですが、そういうお話であっていますか? > ・ファイルシステムの空き容量に変化があるか確認する(変化なく892828のまま) 解説にもあるとおり「同じ実体を参照するハードリンクは同じinode番号を持」つので、inodeテーブル上の情報が増えたり減ったりするわけではなく、「同じinode番号(ファイルシステム上の同じデータの位置)」を別の名前で参照しているだけですから、動的inodeであろうがなかろうが容量消費しないということだと理解しています。

m miki_y

2024/03/30 15:56

ありがとうございます。 うまく説明できずすみません。 例えば、あるfile.txtに対するハードリンクを ①~/hoge/linkfile.txtに作ったとします。 同様に②~/piyo/linkfile2.txt にも同じ実体に対するハードリンクを作ったとします。 この場合、両者とも同じ実体を指すとしても、①と②でリンクの置かれるディレクトリ名もファイル名も異なりますし、それら(パスとファイル名)に関する情報は何かしらどこかに持っておかないといけないと思うのです。 もっと極端に、これと同じ実体に対するハードリンクを、全く別々の場所に別々の名前で、さらに100万個作った場合は?、、、と考えていくと、 各リンクのパスに関する情報はどうしたって保持しておく必要があり、いくらなんでも0Byteというわけにはいかないと思うのです。 この理屈でいくと、静的inodeでも動的inodeでも、ハードリンクを何百万個、何千万個作ってもハードディスクの容量が一切消費されないというのはありえないのでは?というのが素朴な疑問となりました。 シンボリックリンクと違いリンクファイルの持つサイズ自体は何個作っても増えるわけではない、と言われると違和感がないのですが、 ハードリンクを何個作っても容量は消費されない、と言われると、上記のように理屈上あり得ないのではないか、と思うのです。 試験対策上は細かいことは考えず容量消費がないと覚えておけばよいと割り切るしかないのは重々分かっていますがどうも引っかかります。

a arashi1977

2024/04/02 22:19

詳細な補足ありがとうございます。 > もっと極端に、これと同じ実体に対するハードリンクを、全く別々の場所に別々の名前で、さらに100万個作った場合は?、、、と考えていくと、 > 各リンクのパスに関する情報はどうしたって保持しておく必要があり、いくらなんでも0Byteというわけにはいかないと思うのです。 > この理屈でいくと、静的inodeでも動的inodeでも、ハードリンクを何百万個、何千万個作ってもハードディスクの容量が一切消費されないというのはありえないのでは?というのが素朴な疑問となりました。 なるほどと思い上記同様の環境で検証しましたが、面白いですね。少なくともbtrfsではmiki_yさんの想像されたのに近しい挙動をしていました。なぜそうなるのかやXFSなど他の動的inodeのファイルシステムだとどうなるのかは暇があれば調べてみたいなと思いました。 とはいえ > 試験対策上は細かいことは考えず容量消費がないと覚えておけばよいと割り切るしかないのは重々分かっていますがどうも引っかかります。 が全てですよね。試験では「ハードリンクとはどういうものか」が問われていると考えられますので、「動的inodeのファイルシステムでリンク先が重複する大量のハードリンクを作成した場合」という特殊な例を前提にはしていないと判断するべきかなぁと思います。

m miki_y

2024/04/03 23:22

私の代わりにいろいろ実験までしていただき感謝です。 たしかに、割り切ってシンプルに考えておくことにしたいと思います。 ありがとうございました。

この返信に対して
コメントを記入できます

この投稿に対して返信しませんか?