c - 无法通过管道传输三个进程
c - Can't pipe three processes
我一直在尝试在 c 中实现以下命令:
猫/etc/passwd |剪切-f1-d: |排序
这是我目前得到的代码。第一个管道工作正常,但第二个管道似乎根本不工作。
我一遍又一遍地检查代码,但没有发现任何错误。谁能提供解决我问题的建议?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int pipe_A[2];
int pipe_B[2];
pipe(pipe_A);
pipe(pipe_B);
pid_t pid_A, pid_B, pid_C;
if( !(pid_A = fork()) ) {
close(1); /* close normal stdout */
dup(pipe_A[1]); /* make stdout same as pipe_A[1] */
close(pipe_A[0]); /* we don't need this */
execlp("/bin/cat", "cat", "/etc/passwd" , NULL);
}
if( !(pid_B = fork()) ) {
close(0); /* close normal stdin */
dup(pipe_A[0]); /* make stdin same as pipe_A[0] */
close(pipe_A[1]); /* we don't need this */
close(1); /* close normal stdout */
dup(pipe_B[1]); /* make stdout same as pipe_B[1] */
close(pipe_B[0]); /* we don't need this */
execlp("/usr/bin/cut", "cut", "-f1", "-d:", NULL);
}
if( !(pid_C = fork()) ) {
close(0); /* close normal stdin */
dup(pipe_B[0]); /* make stdin same as pipe_B[0] */
close(pipe_B[1]); /* we don't need this */
execlp("/usr/bin/sort", "sort", NULL);
}
return 0;
}
谢谢。
问题是您到处都在泄漏打开的 FD。请注意,每次您调用 fork 时,所有打开的管道都由子进程继承,但具有重复 FD 的管道无法正常工作。
例如,cat
继承了pipe_B
的读写FD。同样,sort
继承了 pipe_A
.
的两个 FD
正确的做法是(但我建议改用 dup2()
):
int main(void)
{
int pipe_A[2];
int pipe_B[2];
pid_t pid_A, pid_B, pid_C;
pipe(pipe_A);
if( !(pid_A = fork()) ) {
close(pipe_A[0]); // A-read not needed here
close(1);
dup(pipe_A[1]);
close(pipe_A[1]); //do not pass A-write twice
execlp("/bin/cat", "cat", "/etc/passwd" , NULL);
}
close(pipe_A[1]); // A-write not needed anymore
pipe(pipe_B); //do not create this pipe until needed
if( !(pid_B = fork()) ) {
close(pipe_B[0]); // B-read not needed here
close(0);
dup(pipe_A[0]);
close(pipe_A[0]); //do not pass A-read twice
close(1);
dup(pipe_B[1]);
close(pipe_B[1]); //do not pass B-write twice
execlp("/usr/bin/cut", "cut", "-f1", "-d:", NULL);
}
close(pipe_A[0]); // A-read not needed anymore
close(pipe_B[1]); // B-write not needed anymore
if( !(pid_C = fork()) ) {
close(0);
dup(pipe_B[0]);
close(pipe_B[0]); // do not pass B-read twice
execlp("/usr/bin/sort", "sort", NULL);
}
close(pipe_B[0]); // B-read not needed anymore
return 0;
}
如果你分析我的代码(如果我写得正确),假设父进程只有 FD 0、1 和 2,每个 execlp()
将得到恰好 3 个 FD,0、1 和2.
我一直在尝试在 c 中实现以下命令: 猫/etc/passwd |剪切-f1-d: |排序
这是我目前得到的代码。第一个管道工作正常,但第二个管道似乎根本不工作。
我一遍又一遍地检查代码,但没有发现任何错误。谁能提供解决我问题的建议?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int pipe_A[2];
int pipe_B[2];
pipe(pipe_A);
pipe(pipe_B);
pid_t pid_A, pid_B, pid_C;
if( !(pid_A = fork()) ) {
close(1); /* close normal stdout */
dup(pipe_A[1]); /* make stdout same as pipe_A[1] */
close(pipe_A[0]); /* we don't need this */
execlp("/bin/cat", "cat", "/etc/passwd" , NULL);
}
if( !(pid_B = fork()) ) {
close(0); /* close normal stdin */
dup(pipe_A[0]); /* make stdin same as pipe_A[0] */
close(pipe_A[1]); /* we don't need this */
close(1); /* close normal stdout */
dup(pipe_B[1]); /* make stdout same as pipe_B[1] */
close(pipe_B[0]); /* we don't need this */
execlp("/usr/bin/cut", "cut", "-f1", "-d:", NULL);
}
if( !(pid_C = fork()) ) {
close(0); /* close normal stdin */
dup(pipe_B[0]); /* make stdin same as pipe_B[0] */
close(pipe_B[1]); /* we don't need this */
execlp("/usr/bin/sort", "sort", NULL);
}
return 0;
}
谢谢。
问题是您到处都在泄漏打开的 FD。请注意,每次您调用 fork 时,所有打开的管道都由子进程继承,但具有重复 FD 的管道无法正常工作。
例如,cat
继承了pipe_B
的读写FD。同样,sort
继承了 pipe_A
.
正确的做法是(但我建议改用 dup2()
):
int main(void)
{
int pipe_A[2];
int pipe_B[2];
pid_t pid_A, pid_B, pid_C;
pipe(pipe_A);
if( !(pid_A = fork()) ) {
close(pipe_A[0]); // A-read not needed here
close(1);
dup(pipe_A[1]);
close(pipe_A[1]); //do not pass A-write twice
execlp("/bin/cat", "cat", "/etc/passwd" , NULL);
}
close(pipe_A[1]); // A-write not needed anymore
pipe(pipe_B); //do not create this pipe until needed
if( !(pid_B = fork()) ) {
close(pipe_B[0]); // B-read not needed here
close(0);
dup(pipe_A[0]);
close(pipe_A[0]); //do not pass A-read twice
close(1);
dup(pipe_B[1]);
close(pipe_B[1]); //do not pass B-write twice
execlp("/usr/bin/cut", "cut", "-f1", "-d:", NULL);
}
close(pipe_A[0]); // A-read not needed anymore
close(pipe_B[1]); // B-write not needed anymore
if( !(pid_C = fork()) ) {
close(0);
dup(pipe_B[0]);
close(pipe_B[0]); // do not pass B-read twice
execlp("/usr/bin/sort", "sort", NULL);
}
close(pipe_B[0]); // B-read not needed anymore
return 0;
}
如果你分析我的代码(如果我写得正确),假设父进程只有 FD 0、1 和 2,每个 execlp()
将得到恰好 3 个 FD,0、1 和2.