歴史的に(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はreaddir
をread(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
によって処理されます)。そのため、プログラムが/dev
でread
システムコールを呼び出すと、成功してディレクトリ一覧を取得できます。
これは事実上UNIXの非常に初期の頃からのホールドオーバーであり、非常に長い間触れられていない機能です。私の一部は、これが後方互換性の理由で取り残されているのではないかと疑っていますが、この機能を削除するのに十分な配慮をしている人はいないため、本当に害はありません。
Lessはテキストファイルビューア、catは任意のデータをコピーするためのツールです。 lessは、独自のチェックを実行して、大量のデータを持つものや非常に奇妙な動作をするものを開かないようにします。一方、catにはそのようなチェックはまったくありません。カーネルが何かを開くことを許可する場合(パイプやデバイス、またはそれより悪いものであっても)、catはそれを読んで。
では、なぜOSはcatがディレクトリを開くことを許可するのですか?伝統的にBSDスタイルのシステムではallディレクトリをファイルとして読み取ることができ、それはプログラムがそもそもディレクトリをリストする方法でした:ディスクに保存されたdirent構造を解釈するだけです。
後に、それらのディスク上の構造は、カーネルが使用するディレントから分岐し始めました。以前はディレクトリが線形リストでしたが、後のファイルシステムはハッシュテーブル、Bツリーなどを使用し始めました。そのため、ディレクトリを直接読み取ることはもはや簡単ではありませんでした–カーネルはこのための専用機能を増やしました。 (それが主な理由であったのか、それとも主にキャッシングなどの他の理由で追加されたのかはわかりません。)
一部のBSDシステムでは、引き続きすべてのディレクトリを読み取り用に開くことができます。ディスクから生データを提供するのか、エミュレートされたdirentリストを代わりに返すのか、ファイルシステムドライバーに決定させるのかはわかりません。
そのため、おそらくmacOSは、カーネルが許可するオペレーティングシステムの1つです限りファイルシステムがデータを提供します。違いは、/dev
は初期の段階でこれを許可するように作成されたdevfs
ファイルシステムにあり、/
は現代では不要であるこの機能を省略したAPFSファイルシステムにあることです。 。
免責事項:私は実際にBSDまたはmacOSに関する調査を行っていません。私はちょうどそれを翼にしている。