研究中です。その他の問題、後ろで何が起こっているのか、/dev/fd/*
これらのファイルが何であるか、サブプロセスがファイルをどのように開いたのか理解していないことに気づきました。
ベストアンサー1
まあ、そこには多くの側面があります。
ファイル記述子
各プロセスに対して、カーネルは開かれたファイルテーブルを維持します(もちろん、別の方法で実装されるかもしれませんが、とにかく見ることができないので、単純なテーブルであると仮定できます)。このテーブルには、ファイルが存在する場所や場所が見つかる、ファイルが開いているモード、現在読み書きする場所、実際にファイルの入出力操作を実行するために必要なその他の情報が含まれています。これで、プロセスはテーブルを読み書きできません。プロセスがファイルを開くと、ファイル記述子であることを返します。これはテーブルへのインデックスにすぎません。
ディレクトリ/dev/fd
と内容
Linuxではdev/fd
実際に/proc/self/fd
。/proc
カーネルがファイルAPIを使用してアクセスする複数の内部データ構造をマップする擬似ファイルシステムです(プログラムの通常のファイル/ディレクトリ/シンボリックリンクのように見えます)。特にすべてのプロセスに関する情報です(ここで名前が由来しました)。シンボリックリンクは、/proc/self
常に現在実行中のプロセス(つまり、それを要求したプロセス、したがってプロセスごとに異なる値が表示される)に関連するディレクトリを参照します。プロセスのディレクトリには、fd
開いている各ファイルに、そのファイルを対象とするファイル記述子(プロセスファイルテーブルのインデックス、前のセクションを参照)の10進表現で名前が付けられたシンボリックリンクを含むサブディレクトリがあります。
サブプロセス生成時のファイル記述子
fork
子プロセスは.Aによってファイル記述子のコピーが作成されますfork
。これは、子プロセスが親プロセスとまったく同じオープンファイルのリストで作成されることを意味します。したがって、子プロセスが開いているファイルの1つを閉じない限り、子プロセスから継承されたファイル記述子にアクセスすると、親プロセスの元のファイル記述子にアクセスするのと同じファイルにアクセスします。
分岐後、最初は同じプロセスの2つのコピーがあり、分岐呼び出しの戻り値のみが異なります(親は子のPIDを取得し、子は0を取得します)。通常、exec
実行可能ファイルの1つのコピーを別のコピーに置き換えるためにフォークが実行されます。開いたファイル記述子は、実行後もまだ存在します。実行前に、プロセスは他のタスク(たとえば、新しいプロセスがインポートしないでくださいファイルを閉じたり、他のファイルを開くなど)を実行したりできます。
無名パイプ
名前のないパイプはカーネルの要求によって生成されたファイル記述子のペアであるため、最初のファイル記述子に書き込まれたすべての内容は2番目のファイル記述子に渡されます。最も一般的な用途は、foo | bar
パイプ構成では、bash
標準出力がfoo
パイプの書き込み部分に置き換えられ、標準入力が読み取り部分に置き換えられることです。 stdinとstdoutはファイルテーブルの最初の2つのエントリ(項目0と1、2は標準エラー)です。することができます)。プロセスがテーブルに直接アクセスできないため、これを行うカーネル関数があります。
プロセスの置き換え
これですべてが準備されているので、プロセス置換がどのように機能するかを確認できます。
- Bashプロセスは、後で作成される2つのプロセス間の通信に使用される名前のないパイプを生成します。
- Bashはプロセスを分岐します
echo
。子プロセス(元のプロセスの正確なコピーbash
)はパイプの読み取り端を閉じ、独自の標準出力をパイプの書き込み端に置き換えます。これがecho
シェル組み込みであることを考慮すると、それ自体bash
で呼び出しを保存できますが、exec
問題ではありません(シェル組み込みも無効になる可能性があり、この場合はexecを実行します/bin/echo
)。 - Bash(元の親)は、
<(echo 1)
名前のないパイプの読み取りの終わりを参照したときに式を疑似ファイルリンクに置き換えました。/dev/fd
- PHPプロセスのBashランチャー(フォーク後もまだbashの[コピー]にあることに注意してください)。新しいプロセスは、名前付きパイプの継承された書き込み側を閉じて別の準備手順を実行しますが、読み取り側は開いたままにします。次にPHPを実行します。
- PHPプログラムは、
/dev/fd/
対応するファイル記述子がまだ開かれているので、パイプの読み出し端に相当します。したがって、PHPプログラムが読み取り用に特定のファイルを開く場合、実際に実行することは、名前のないパイプのsecond
読み取り終了のためのファイル記述子を生成することです。しかし、問題ありません。どちらからでも読むことができます。 - これで、PHPプログラムは新しいファイル記述子を介してパイプの読み取り端を読み取ることができるため、
echo
同じパイプの書き込み端からコマンドの標準出力を受け取ることができます。