2

配管を処理する単純なシェルを作成しています。動作するコードはありますが、内部でどのように動作するのかよくわかりません。これは、理解するのに助けが必要な変更されたコード スニペットです (短くするためにエラー チェックを削除しました)。

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);
}

質問には推測がありますが、推測はそれだけです。ここに私が持っている質問があります:

  1. ブロッキングはどこで実行されますか? 私が見たすべてのサンプル コードで、ブロッキングread()write()提供していますが、ここではそれらを使用する必要はありませんでした。パイプの読み取り側を指すように STDIN をコピーし、パイプの書き込み側を指すように STDOUT をコピーするだけです。私が推測しているのは、dup2(fd[0], 0)実行後にSTDINがブロッキングを行っているということです。これは正しいです?
  2. 私が理解していることから、実行中のプロセスごとに、ファイル テーブル内の開いているファイルを指す記述子テーブルがあります。プロセスが STDIN、STDOUT、または STDERR をリダイレクトするとどうなりますか? これらのファイル記述子は、すべてのプロセスの記述子テーブルで共有されていますか? それとも、プロセスごとにコピーがありますか? 1 つをリダイレクトすると、それらすべてに変更が反映されますか?
  3. への呼び出し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]);
    }
    
  4. これは、配管プロセスがどのように機能するかについての概念的な質問です。ファイル ハンドル によって参照されるパイプの読み取り側と、ファイル ハンドル によってfd[0]参照されるパイプの書き込み側がありますfd[1]。パイプ自体は、バイト ストリームによって表される単なる抽象化です。ファイルハンドルは開いているファイルを表していますよね?つまり、システムのどこかにfd[1]、パイプを介して送信したいすべての情報が書き込まれたファイル ( で示される) があるということでしょうか? そして、バイト ストリームを介してその情報をプッシュした後、fd[0]すべての情報が書き込まれたファイル ( で示される) が存在し、パイプの抽象化が作成されます。

4

2 に答える 2

2

まず第一に、通常、親プロセスではなく、execveプロセスで呼び出します。親は自分の子供が誰であるかを知っていますが、その逆ではないことを忘れないでください。

パイプの下には実際にはオペレーティング システムによって処理されるバッファがあり、バッファがいっぱいの場合はパイプへの書き込みがブロックされ、読み取るものが何もない場合はパイプへの読み取りがブロックされることが保証されます。これが、あなたが経験するブロッキングの原因です。

バッファが小さく、コンピュータが低速だった古き良き時代には、たとえば数十キロバイト程度の少量のデータであっても、断続的に起動される読み取りプロセスに実際に頼ることができました。現在、多くの場合、読み取りプロセスは 1 回のショットで入力を取得します。

于 2014-01-10T00:02:02.657 に答える