我需要实现这样的IPC模式:
runtime data -> filter1 -> filter2 -> output
。 (与data | filter1 | filter2
相同)。
我可以将数据传递给第一个过滤器,但是第二个我不能(可能因为在第一个孩子stdout fd没有关闭)。如何正确实现这样的架构?
P.S。 filter1和filter2只是从stdin读取并写入stdout。
我的代码:
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);
}
}
答案 0 :(得分:1)
你太早关闭管道了。通常,在fd2[0]
中使用之前,请关闭dup2
。当您在第二个分叉之前重定向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 {
...