パイプの一端にfdの読み取りと書き込みの両方がありますか?

パイプの一端にfdの読み取りと書き込みの両方がありますか?

私が知っている限り、パイプの一端はfdを読み書きすることができ、もう一方の端はfdを読み書きできます。これが私たちがusingを使って書き込むときにパイプの同じ側の読み出し端を閉じ、fd[1]usingを使って2番目の端から読み取るときにその端の読み出し端を閉じる理由です。私は正しいですか?fd[0]fd[0]fd[1]

ベストアンサー1

はい、パイプライン()で作成されたパイプラインには2つのファイル記述子があります。fd[0]読み書きfd[1]用。

いいえ、パイプの両端を閉じる必要はありません。双方向通信に使用できます。

編集:コメントでこれがどのようなものに関連しているのか疑問に思いましたので、ls | lessこれについても説明します。

シェルには、0(stdin)、1(stdout)、2(stderr)の3つのオープンファイル記述子があります。シェルがコマンドを実行すると、次のことが行われます(少し単純化されました。

pid = fork();
if(pid == 0) {
    /* I am the child */
    execve(...); /* Whatever the user asked for */
}
else {
    waitpid(pid); /* Wait for child to complete */
}

ファイル記述子0、1、2は子プロセスによって継承されるため、入力/出力は期待どおりに機能します。これにより、ls | lessリダイレクト時に若干異なることが発生します。

int pipe[2];
pipe(pipe, 0);

pid1 = fork();
if(pid1 == 0) {
    /* This is ls, we need to remap stdout to the pipe. We don't care about reading from the pipe */
    close(pipe[0]);
    close(1);
    dup2(pipe[1], 1);
    execve(...);
}
else {
    pid2 = fork();
    if(pid2 == 0) {
        /* This is less, it reads from the pipe */
        close(pipe[1]);
        close(0);
        dup2(pipe[0], 0);
        execve(...);
    }
    else {
        waitpid(pid1);
        waitpid(pid2);
    }
}

したがって、シェルはパイプを作成して分岐し、実行前にパイプをサブプロセスのstdinまたはstdoutに再マップして、データがプロセス1からプロセス2に流れることができます。シェルパイプは双方向ではないため、パイプの一方の端だけを使用し、もう一方の端を閉じます(ファイル記述子を標準入力または標準出力にコピーした後、実際にもう一方の端も閉じます)。

おすすめ記事