Linux上のすべてがファイルである場合、ディレクトリとは何ですか?


17

多くの場合、初心者は「すべてはLinux / Unix上のファイルです」というフレーズを聞きます。ただし、ディレクトリは何ですか?それらはファイルとどう違うのですか?

回答:


22

注:もともとこれはlsコマンド内の現在のディレクトリが自分自身にリンクされていると識別される理由に対する私の回答をサポートするために書かれたものですか?しかし、私はこれが単独で立つに値するトピックであり、したがってこのQ&Aであると感じました

Unix / Linuxファイルシステムとファイルを理解する:すべてはiノードです

本質的に、ディレクトリはエントリとそのIDのリストを含む特別なファイルです。

議論を始める前に、いくつかの用語を区別し、どのディレクトリとファイルが実際に表しているのかを理解することが重要です。Unix / Linuxの「すべてはファイルです」という表現を聞いたことがあるかもしれません。さて、ユーザーがファイルとしてよく理解するのは次のとおりです/etc/passwd。-パスと名前を持つオブジェクト。実際には、名前(ディレクトリやファイルなど)は単なるテキストの文字列であり、実際のオブジェクトのプロパティです。そのオブジェクトは、iノードまたはI番号と呼ばれ、iノードテーブルのディスクに保存されます。オープンプログラムにもiノードテーブルがありますが、現時点ではそれは問題ではありません。

Unixのディレクトリの概念は、ケントンプソンが1989年のインタビューで述べたとおりです。

...そして、それらのファイルのいくつかは、名前とI番号を含むディレクトリでした。

興味深い観察から行うことができ、1972年にデニス・リッチーの話ということ

「...ディレクトリは実際にはファイルにすぎませんが、その内容はシステムによって制御され、その内容は他のファイルの名前です(ディレクトリは他のシステムではカタログと呼ばれることもあります。)」

...しかし、トークのどこにもiノードについての言及はありません。ただし、状態に関する1971年のマニュアルformat of directories

ファイルがディレクトリであるという事実は、そのiノードエントリのフラグワードのビットで示されます。

ディレクトリエントリの長さは10バイトです。最初の単語はiです。エントリが表すファイルのノード(ゼロでない場合)。ゼロの場合、エントリは空です。

だから、それは最初からそこにありました。

ディレクトリとiノードのペアリングについては、ディレクトリ構造がUNIXファイルシステムどのように保存されるかについても説明しています。。ディレクトリ自体はデータ構造、より具体的には、オブジェクトのリスト(アクセス権、タイプ、所有者、サイズなど)を指すオブジェクト(ファイルとiノード番号)のリストです。したがって、各ディレクトリには独自のiノード番号が含まれ、次にファイル名とそのiノード番号が含まれます。最も有名なのは、ディレクトリであるiノード#2/です。(注、それにもかかわらず/devそして/run彼らは、ファイルシステムのルートフォルダですので、そう、仮想ファイルシステムです、彼らはまた、inodeを持っている2; すなわち、iノードはそれ自身のファイルシステム上で一意ですが、複数のファイルシステムが接続されている場合、一意でないiノードがあります)。リンクされた質問から借用した図は、おそらくより簡潔に説明しています。

Directory-iNode-Block

stat()Linuxのように、iノードに保存されているすべての情報には、システムコールを介してアクセスできますman 7 inode

各ファイルには、ファイルに関するメタデータを含むiノードがあります。アプリケーションは、stat構造体を返すstat(2)(または関連する呼び出し)、またはstatx構造体を返すstatx(2)を使用して、このメタデータを取得できます。

iノード番号(ref1ref2)のみを知っているファイルにアクセスすることは可能ですか?一部のUnix実装では可能ですが、許可とアクセスのチェックをバイパスするため、Linuxでは実装されず、ファイルシステムツリーを(find <DIR> -inum 1234たとえば経由して)走査して、ファイル名とそれに対応するiノードを取得する必要があります。

ソースコードレベルでは、Linuxカーネルソースで定義され、ext3およびext4ファイルシステム(Ubuntuのデフォルト)など、Unix / Linuxオペレーティングシステムで動作する多くのファイルシステムでも採用されています。興味深いことに、データは単なる情報のブロックであるため、Linuxには実際には、inodeがパイプ()かどうかを判別できるinode_init_always関数がありますinode->i_pipe。はい、ソケットとパイプも技術的にはファイルです-匿名ファイルで、ディスク上にファイル名がない場合があります。FIFOおよびUnixドメインソケットは、ファイルシステム上にファイル名を持っています。

データ自体は一意ですが、iノード番号は一意ではありません。foob​​arと呼ばれるfooへのハードリンクがある場合は、iノード123も指します。このiノード自体には、そのiノードが占有しているディスクスペースの実際のブロックに関する情報が含まれています。技術的.には、これがディレクトリfilenameにリンクされる方法です。まあ、ほとんど:あなたは、Linuxを自分のディレクトリへのハードリンクを作成することはできませんが、ファイルシステムは、唯一持っていることの制約になり非常に規律の方法、内のディレクトリへのハードリンク許可することができます.し、..ハードリンクなどを。

ディレクトリツリー

ファイルシステムは、ツリーデータ構造の1つとしてディレクトリツリーを実装します。特に、

  • ext3およびext4はHTreeを使用します
  • xfsはB +ツリーを使用します
  • zfsはハッシュツリーを使用します

ここで重要な点は、ディレクトリ自体がツリー内のノードであり、サブディレクトリが子ノードであり、各子が親ノードに戻るリンクを持っていることです。したがって、ディレクトリリンクの場合、ベアディレクトリのiノード数は最小2(ディレクトリ名/home/example/へのリンクおよびselfへのリンク/home/example/.)であり、追加の各サブディレクトリは追加のリンク/ノードです。

# new directory has link count of 2
$ stat --format=%h .
2
# Adding subdirectories increases link count
$ mkdir subdir1
$ stat --format=%h .
3
$ mkdir subdir2
$ stat --format=%h .
4
# Count of links for root
$ stat --format=%h /
25
# Count of subdirectories, minus .
$ find / -maxdepth 1 -type d | wc -l
24

図は上にあるイアンD.アレンのコースページを示して簡略化され非常に明確図:

WRONG - names on things      RIGHT - names above things
=======================      ==========================

    R O O T            --->         [etc,bin,home]   <-- ROOT directory
   /   |   \                         /    |      \
etc   bin   home       --->  [passwd]  [ls,rm]  [abcd0001]
 |   /   \    \                 |      /    \       |
 |  ls   rm  abcd0001  --->     |  <data>  <data>  [.bashrc]
 |               |              |                   |
passwd       .bashrc   --->  <data>                <data>

右図の唯一の不正確な点は、ファイルが技術的にディレクトリツリー自体にあると見なされていないことです。ファイルを追加してもリンク数に影響はありません。

$ mkdir subdir2
$ stat --format=%h .
4
# Adding files doesn't make difference
$ cp /etc/passwd passwd.copy
$ stat --format=%h .
4

ファイルのようにディレクトリにアクセスする

Linus Torvaldsを引用するには:

「すべてがファイル」というのは、ランダムなファイル名があるということではありません(実際、ソケットとパイプは「ファイル」と「ファイル名」が互いに関係ないことを示しています)。さまざまなものを操作するツール。

ディレクトリは、ファイルの単なる特殊なケースであることを考えると、自然に私たちがすることができるAPIがあるように持って開く / 読み込み / 書き込み / クローズそれら同様の方法で通常のファイルに。

そこで、dirent.hCライブラリが配置され、dirent構造を定義します。この構造は、man 3 readdirで見つけることができます。

   struct dirent {
       ino_t          d_ino;       /* Inode number */
       off_t          d_off;       /* Not an offset; see below */
       unsigned short d_reclen;    /* Length of this record */
       unsigned char  d_type;      /* Type of file; not supported
                                      by all filesystem types */
       char           d_name[256]; /* Null-terminated filename */
   };

したがって、Cコードではを定義する必要がありstruct dirent *entry_p、ディレクトリを開いてopendir()読み取りを開始するとreaddir()、各entry_p構造体に各アイテムが格納されます。もちろん、各アイテムには、dirent上記のテンプレートで定義されたフィールドが含まれます。

これがどのように機能するかの実用的な例は、現在の作業ディレクトリ内のファイルとそのiノード番号をリストする方法に関する私の答えにあります

fdopenPOSIXマニュアルには「[dot] dotおよびdot-dotのディレクトリエントリはオプションです」と記載 struct direntされてd_nameおり、readdirの手動状態d_inoフィールドとフィールドのみが必要であることに注意してください。

ディレクトリへの「書き込み」に関する注意:ディレクトリへの書き込みは、エントリの「リスト」を変更します。したがって、ファイルの作成または削除はディレクトリの書き込み許可に直接関連付けられ、ファイルの追加/削除はそのディレクトリに対する書き込み操作です。


2
ソケットをファイルとして受け入れることを拒否します;)「すべてがファイルとしてアクセス可能」の方が正確でしょうか?
リンツウィンド

@Rinzwindまあ、「ファイルとしてすべてにアクセスできる」というフレーズは正確です。通常のファイルは持っているopen()read()ソケットは持っているconnect()read()も。より正確なのは、「ファイル」は実際にディスクまたはメモリに保存された「データ」であり、一部のファイルは匿名で、ファイル名がないということです。通常、ユーザーはデスクトップ上のアイコンの観点からファイルを考えますが、それだけが存在するわけではありません。unix.stackexchange.com/a/116616/85039
Sergiy Kolodyazhnyy

質問は、ディレクトリがファイルであるかどうかに関するものでした。そしてそれは。ソケットは、FIFO名前付きパイプと一緒にほとんど別の質問になる可能性があります。
WinEunuuchs2Unix

まあ、私はこれまでのパイプについての答えを得た:askubuntu.com/a/1074550/295286は たぶん、FIFOは次のだろう
Sergiy Kolodyazhnyy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.