web-dev-qa-db-ja.com

なぜ私は/ devを猫にすることができますか?

cat /devできます、ls /devできます、less /devできません。 catがこのディレクトリをcatとし、他のディレクトリをしないのはなぜですか?

Picture of this behaviour in zsh.

40
haboutnnah

歴史的に(V7 UNIXまで、または1979年頃)、readシステムコールはファイルとディレクトリの両方で機能しました。ディレクトリに対するreadは、ディレクトリエントリを取得するためにユーザープログラムが解析する単純なデータ構造を返します。確かに、V7のlsツールはまさにこれを行いました - ディレクトリのreadは、結果として得られるデータ構造を解析し、構造化リスト形式で出力します。

ファイルシステムがより複雑になるにつれて、プログラムがread(directory)の出力を解析するのを助けるためにreaddirライブラリ関数が追加されるまで、この「単純な」データ構造はより複雑になりました。システムやファイルシステムが異なればディスク上のフォーマットも異なる可能性があり、これは複雑になっていました。

SunがNetwork File System(NFS)を導入したとき、彼らはディスク上のディレクトリ構造を完全に抽象化したかったのです。しかし、彼らのread(directory)がプラットフォームに依存しないディレクトリの表現を返すようにする代わりに、彼らは新しいシステムコールを追加しました - getdirents - そしてネットワークマウントされたディレクトリへのreadを禁止しました。このシステムコールは、さまざまなUNIXフレーバーのすべてのディレクトリで動作するように急速に調整され、ディレクトリの内容を取得するためのデフォルトの方法になりました。 (歴史は https://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory から抽象化されました)

readdirは現在ディレクトリを読み込むためのデフォルトの方法なので、read(directory)は通常ほとんどのOSで実装されていません(-EISDIRを返す)(たとえば、QNXはreaddirread(directory)として実装する注目すべき例外です)。しかし、最近のほとんどのカーネルの「仮想ファイルシステム」設計では、ディレクトリの読み取りが機能するかどうかにかかわらず、実際には個々のファイルシステムによって異なります。

そして確かに、macOSでは、/devマウントポイントの基礎となるdevfsファイルシステムは実際に読み込みをサポートします( https://github.com/Apple/darwin-xnu/blob/xnu-4570.1.46/bsd /miscfs/devfs/devfs_vnops.c#L629 ):

static int
devfs_read(struct vnop_read_args *ap)
{
        devnode_t * dn_p = VTODN(ap->a_vp);

    switch (ap->a_vp->v_type) {
      case VDIR: {
          dn_p->dn_access = 1;

          return VNOP_READDIR(ap->a_vp, ap->a_uio, 0, NULL, NULL, ap->a_context);

/devを読み込もうとすると、これは明示的にREADDIRを呼び出します(/devの下のファイルの読み取りは別の関数 - devfsspec_readによって処理されます)。そのため、プログラムが/devreadシステムコールを呼び出すと、成功してディレクトリ一覧を取得できます。

これは事実上UNIXの非常に初期の頃からのホールドオーバーであり、非常に長い間触れられていない機能です。私の一部は、これが後方互換性の理由で取り残されているのではないかと疑っていますが、この機能を削除するのに十分な配慮をしている人はいないため、本当に害はありません。

42
nneonneo

Lessはテキストファイルビューア、catは任意のデータをコピーするためのツールです。 lessは、独自のチェックを実行して、大量のデータを持つものや非常に奇妙な動作をするものを開かないようにします。一方、catにはそのようなチェックはまったくありません。カーネルが何かを開くことを許可する場合(パイプやデバイス、またはそれより悪いものであっても)、catはそれを読んで。

では、なぜOSはcatがディレクトリを開くことを許可するのですか?伝統的にBSDスタイルのシステムではallディレクトリをファイルとして読み取ることができ、それはプログラムがそもそもディレクトリをリストする方法でした:ディスクに保存されたdirent構造を解釈するだけです。

後に、それらのディスク上の構造は、カーネルが使用するディレントから分岐し始めました。以前はディレクトリが線形​​リストでしたが、後のファイルシステムはハッシュテーブル、Bツリーなどを使用し始めました。そのため、ディレクトリを直接読み取ることはもはや簡単ではありませんでした–カーネルはこのための専用機能を増やしました。 (それが主な理由であったのか、それとも主にキャッシングなどの他の理由で追加されたのかはわかりません。)

一部のBSDシステムでは、引き続きすべてのディレクトリを読み取り用に開くことができます。ディスクから生データを提供するのか、エミュレートされたdirentリストを代わりに返すのか、ファイルシステムドライバーに決定させるのかはわかりません。

そのため、おそらくmacOSは、カーネルが許可するオペレーティングシステムの1つです限りファイルシステムがデータを提供します。違いは、/devは初期の段階でこれを許可するように作成されたdevfsファイルシステムにあり、/は現代では不要であるこの機能を省略したAPFSファイルシステムにあることです。 。

免責事項:私は実際にBSDまたはmacOSに関する調査を行っていません。私はちょうどそれを翼にしている。

36
grawity