配管を処理する単純なシェルを作成しています。動作するコードはありますが、内部でどのように動作するのかよくわかりません。これは、理解するのに助けが必要な変更されたコード スニペットです (短くするためにエラー チェックを削除しました)。
int fd[2];
pipe(fd);
if (fork()) { /* parent code */
close(fd[1]);
dup2(fd[0], 0);
/* call to execve() here */
} else { /* child code */
close(fd[0]);
dup2(fd[1], 1);
}
質問には推測がありますが、推測はそれだけです。ここに私が持っている質問があります:
- ブロッキングはどこで実行されますか? 私が見たすべてのサンプル コードで、ブロッキング
read()
をwrite()
提供していますが、ここではそれらを使用する必要はありませんでした。パイプの読み取り側を指すように STDIN をコピーし、パイプの書き込み側を指すように STDOUT をコピーするだけです。私が推測しているのは、dup2(fd[0], 0)
実行後にSTDINがブロッキングを行っているということです。これは正しいです? - 私が理解していることから、実行中のプロセスごとに、ファイル テーブル内の開いているファイルを指す記述子テーブルがあります。プロセスが STDIN、STDOUT、または STDERR をリダイレクトするとどうなりますか? これらのファイル記述子は、すべてのプロセスの記述子テーブルで共有されていますか? それとも、プロセスごとにコピーがありますか? 1 つをリダイレクトすると、それらすべてに変更が反映されますか?
への呼び出し
pipe()
とそれに続くへの呼び出しの後、fork()
開いているパイプの 4 つの「端」があります。親によってアクセスされる読み取りおよび書き込み端と、子によってアクセスされる読み取りおよび書き込み端です。私のコードでは、親の書き込み側と子の読み取り側を閉じています。ただし、パイプを使い終わった後、残りの 2 つの端は閉じません。コードは正常に動作するので、ある種の暗黙の終了が行われていると思いますが、それはすべて当て推量です。このように、残りの 2 つの端を閉じるために明示的な呼び出しを追加する必要がありますか?int fd[2]; pipe(fd); if (fork()) { /* parent code */ close(fd[1]); dup2(fd[0], 0); /* call to execve() here */ close(fd[0]); } else { /* child code */ close(fd[0]); dup2(fd[1], 1); close(fd[1]); }
これは、配管プロセスがどのように機能するかについての概念的な質問です。ファイル ハンドル によって参照されるパイプの読み取り側と、ファイル ハンドル によって
fd[0]
参照されるパイプの書き込み側がありますfd[1]
。パイプ自体は、バイト ストリームによって表される単なる抽象化です。ファイルハンドルは開いているファイルを表していますよね?つまり、システムのどこかにfd[1]
、パイプを介して送信したいすべての情報が書き込まれたファイル ( で示される) があるということでしょうか? そして、バイト ストリームを介してその情報をプッシュした後、fd[0]
すべての情報が書き込まれたファイル ( で示される) が存在し、パイプの抽象化が作成されます。