ls
フォークされた子は、実行されたプロセスが書き込み(の場合)および読み取り(の場合)するファイル記述子を保証するため、表示されたコードはほぼ機能します(多くのコーナーをカットしますが、機能しますwc
) 。パイプの適切な端です。もうする必要はありません。標準入力はファイル記述子0であるためwc
、(ファイル名)引数なしで標準入力から読み取ります。 ls
エラーメッセージを書き込んでいない限り、常に標準出力であるファイル記述子1に書き込みます。
コードスニペットには3つのプロセスがあります。親プロセスと2つの子(それぞれから1つずつ)fork()
。親プロセスは、パイプの両端も閉じる必要があります。1つだけ閉じます。
一般に、パイプファイル記述子を実行dup()
またはdup2()
呼び出した後、パイプの両端を閉じる必要があります。ls
データを生成して終了するので、ここでそれを回避します。すべての状況でそうなるわけではありません。
コメント:
/* Set stdout to the input side of the pipe, and run 'ls'. */
不正確です。stdout
入力側ではなく、パイプの出力側に設定しています。
execv()
呼び出し後にエラーが終了するはずです。それらが失敗した場合、それらは戻り、プロセスは大混乱を引き起こす可能性があります(たとえば、ls
失敗した場合、2つのコピーがwc
実行されることになります。
各プロセスでパイプの両端を注意深く閉じることに注意してください。親プロセスは、両方の子を起動すると、パイプを使用できなくなります。早い段階で閉じるコードを残しました(ただし、次のコードも実行された場合にのみ実行されたためfiledes[1]
、明示的なブロックから削除しました)。ファイルを閉じる必要がある3つのコードパスのそれぞれにペアを保持していた可能性があります。else
else
closes()
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void)
{
int filedes[2];
int corpse;
int status;
pipe(filedes);
/* Run LS. */
pid_t pid = fork();
if (pid == 0)
{
/* Set stdout to the output side of the pipe, and run 'ls'. */
dup2(filedes[1], 1);
close(filedes[1]);
close(filedes[0]);
char *argv[] = {"ls", NULL};
execv("/bin/ls", argv);
fprintf(stderr, "Failed to execute /bin/ls\n");
exit(1);
}
/* Close the input side of the pipe, to prevent it staying open. */
close(filedes[1]);
/* Run WC. */
pid = fork();
if (pid == 0)
{
/* Set stdin to the input side of the pipe, and run 'wc'. */
dup2(filedes[0], 0);
close(filedes[0]);
char *argv[] = {"wc", NULL};
execv("/usr/bin/wc", argv);
fprintf(stderr, "Failed to execute /usr/bin/wc\n");
exit(1);
}
close(filedes[0]);
while ((corpse = waitpid(-1, &status, 0)) > 0)
printf("PID %d died 0x%.4X\n", corpse, status);
return(0);
}
出力例:
$ ./pipes-14312939
32 32 389
PID 75954 died 0x0000
PID 75955 died 0x0000
$