多管道不起作用
Multi-pipe does not work
我需要实现这样的 IPC 模式:
runtime data -> filter1 -> filter2 -> output
。 (与 data | filter1 | filter2
相同)。
我可以将数据传递给第一个过滤器,但不能传递给第二个过滤器(可能是因为第一个子 stdout fd 未关闭)。如何正确实施这种模式?
P.S。 filter1 和 filter2 只是从标准输入读取并写入标准输出。
我的代码:
int main() {
int fd1[2];
pipe(fd1);
pid_t pid1;
if ((pid1 = fork()) > 0) {
char data[] = "Hello world!";
close(fd1[0]);
write(fd1[1], data, sizeof(data));
close(fd1[1]);
wait(NULL);
exit(EXIT_SUCCESS);
} else if (pid1 == 0) {
int fd2[2];
pipe(fd2);
pid_t pid2;
dup2(fd1[0], STDIN_FILENO);
dup2(fd2[1], STDOUT_FILENO);
close(fd1[0]); close(fd1[1]);
close(fd2[0]); close(fd2[1]);
if ((pid2 = fork()) > 0) {
execl("./upcase", "upcase", NULL);
perror("execl");
exit(EXIT_FAILURE);
} else if (pid2 == 0) {
close(fd1[0]); close(fd1[1]);
dup2(fd2[0], STDIN_FILENO);
close(fd2[0]); close(fd2[1]);
execl("./reverse", "reverse", NULL);
perror("execl");
exit(EXIT_FAILURE);
} else {
perror("pid2");
exit(EXIT_FAILURE);
}
} else {
perror("pid1");
exit(EXIT_FAILURE);
}
}
您关闭管道的时间过早。通常,在 dup2
中使用它之前先关闭 fd2[0]
。当您在第二个分支之前重定向 FILENO_STDOUT 时,第二个过滤器不再访问原始标准输出。
以下代码有效:
int main() {
int fd1[2];
pipe(fd1);
pid_t pid1;
if ((pid1 = fork()) > 0) {
char data[] = "Hello world!";
close(fd1[0]); // OK, will no longer be used
write(fd1[1], data, sizeof(data));
close(fd1[1]);
wait(NULL);
exit(EXIT_SUCCESS);
} else if (pid1 == 0) {
int fd2[2];
pipe(fd2);
pid_t pid2;
close(fd1[1]); // OK, no used from here
if ((pid2 = fork()) > 0) {
dup2(fd1[0], STDIN_FILENO); // redirections for filter1
dup2(fd2[1], STDOUT_FILENO);
close(fd1[0]); // close everything except stdin and stdout
close(fd2[0]); close(fd2[1]);
execl("./upcase", "upcase", NULL);
perror("execl upcase");
exit(EXIT_FAILURE);
} else if (pid2 == 0) {
close(fd1[0]); // not used here
dup2(fd2[0], STDIN_FILENO); // redirection for filter2
close(fd2[0]); close(fd2[1]); // close all what remains
execl("./reverse", "reverse", NULL);
perror("execl reverse");
exit(EXIT_FAILURE);
} else {
...
我需要实现这样的 IPC 模式:
runtime data -> filter1 -> filter2 -> output
。 (与 data | filter1 | filter2
相同)。
我可以将数据传递给第一个过滤器,但不能传递给第二个过滤器(可能是因为第一个子 stdout fd 未关闭)。如何正确实施这种模式?
P.S。 filter1 和 filter2 只是从标准输入读取并写入标准输出。
我的代码:
int main() {
int fd1[2];
pipe(fd1);
pid_t pid1;
if ((pid1 = fork()) > 0) {
char data[] = "Hello world!";
close(fd1[0]);
write(fd1[1], data, sizeof(data));
close(fd1[1]);
wait(NULL);
exit(EXIT_SUCCESS);
} else if (pid1 == 0) {
int fd2[2];
pipe(fd2);
pid_t pid2;
dup2(fd1[0], STDIN_FILENO);
dup2(fd2[1], STDOUT_FILENO);
close(fd1[0]); close(fd1[1]);
close(fd2[0]); close(fd2[1]);
if ((pid2 = fork()) > 0) {
execl("./upcase", "upcase", NULL);
perror("execl");
exit(EXIT_FAILURE);
} else if (pid2 == 0) {
close(fd1[0]); close(fd1[1]);
dup2(fd2[0], STDIN_FILENO);
close(fd2[0]); close(fd2[1]);
execl("./reverse", "reverse", NULL);
perror("execl");
exit(EXIT_FAILURE);
} else {
perror("pid2");
exit(EXIT_FAILURE);
}
} else {
perror("pid1");
exit(EXIT_FAILURE);
}
}
您关闭管道的时间过早。通常,在 dup2
中使用它之前先关闭 fd2[0]
。当您在第二个分支之前重定向 FILENO_STDOUT 时,第二个过滤器不再访问原始标准输出。
以下代码有效:
int main() {
int fd1[2];
pipe(fd1);
pid_t pid1;
if ((pid1 = fork()) > 0) {
char data[] = "Hello world!";
close(fd1[0]); // OK, will no longer be used
write(fd1[1], data, sizeof(data));
close(fd1[1]);
wait(NULL);
exit(EXIT_SUCCESS);
} else if (pid1 == 0) {
int fd2[2];
pipe(fd2);
pid_t pid2;
close(fd1[1]); // OK, no used from here
if ((pid2 = fork()) > 0) {
dup2(fd1[0], STDIN_FILENO); // redirections for filter1
dup2(fd2[1], STDOUT_FILENO);
close(fd1[0]); // close everything except stdin and stdout
close(fd2[0]); close(fd2[1]);
execl("./upcase", "upcase", NULL);
perror("execl upcase");
exit(EXIT_FAILURE);
} else if (pid2 == 0) {
close(fd1[0]); // not used here
dup2(fd2[0], STDIN_FILENO); // redirection for filter2
close(fd2[0]); close(fd2[1]); // close all what remains
execl("./reverse", "reverse", NULL);
perror("execl reverse");
exit(EXIT_FAILURE);
} else {
...