我正在尝试使用系统调用fork和pipe在C中cat /etc/passwd | grep 1000 | cut -d: -f1
实现此命令。
当我只使用两个命令时cmd1 | cmd2
所以 1 个分支它工作正常,但是当我使用超过 2 个进程时,出现问题
这是我的代码,我认为问题出在大父块上
更新 :
我关闭了一些未关闭的文件描述符
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
int main(){
int fd[2], fd2[2];
pid_t pid, pid2;
char str[100];
if(pipe(fd) != 0){
fprintf(stderr, "Error pipe.n");
return 1;
}
if(pipe(fd2) != 0){
fprintf(stderr, "Error pipe.n");
return 1;
}
do{
pid = fork();
}while(pid == -1 && errno == EAGAIN);
if(pid == -1){
perror("fork()");
exit(1);
}
if(pid == 0){
pid2 = fork();
if(pid2 == 0){
// fprintf(stderr, "1 - Grand Childn");
close(fd[0]);
dup2(fd[1], 1);
close(fd[1]);
execlp("cat", "cat", "/etc/passwd", NULL);
perror("cat error");
}else{
wait(&pid2);
// fprintf(stderr, "2 - Childn");
close(fd[1]);
dup2(fd[0], 0);
close(fd[0]);
up2(fd2[1], 1);
close(fd2[1]);
execlp("grep", "grep", "1000", NULL);
perror("grep failed");
}
return 1;
}else{
wait(&pid);
// fprintf(stderr, "3 - Parentn");
close(fd[0]);
dup2(fd2[0], 0);
close(fd2[0]);
execlp("cut", "cut", "-d:", "-f1", NULL);
perror("cut failed");
return 1;
}
return 0;
}
您需要关闭孩子和父母中所有未使用的文件描述符!在这种情况下,使用 dup2(( 时,与管道关联的所有文件描述符都可以关闭。
为了清楚起见,我使用了宏作为与 stdin 和 stdout 关联的文件描述符。宏STDIN_FILENO和STDOUT_FILENO在 unistd.h 中声明。
不需要等待孩子(wait(&pid);
和wait(&pid2);
(。在运行grep
之前,您不需要等待cat
结束,因为 grep 会在它们到来时处理它们。管道应该有一个很大的缓冲区,比如 65536 字节,所以在 cat 命令结束后,数据将被缓冲在管道中,但这不是可以指望的东西。
以下代码(只需稍作更改(即可工作:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
int main(){
int fd[2], fd2[2];
pid_t pid, pid2;
char str[100];
if(pipe(fd) != 0){
fprintf(stderr, "Error pipe.n");
return 1;
}
if(pipe(fd2) != 0){
fprintf(stderr, "Error pipe.n");
return 1;
}
do{
pid = fork();
}while(pid == -1 && errno == EAGAIN);
if(pid == -1){
perror("fork()");
exit(1);
}
if(pid == 0){
pid2 = fork();
if(pid2 == 0){
// fprintf(stderr, "1 - Grand Childn");
dup2(fd[1], STDOUT_FILENO); // 1);
close(fd[0]);
close(fd[1]);
close(fd2[1]);
close(fd2[0]);
execlp("cat", "cat", "/etc/passwd", NULL);
perror("cat error");
}else{
// wait(&pid2);
// fprintf(stderr, "2 - Childn");
dup2(fd[0], STDIN_FILENO); //0);
dup2(fd2[1], STDOUT_FILENO); // 1);
close(fd[0]);
close(fd[1]);
close(fd2[1]);
close(fd2[0]);
execlp("grep", "grep", "1000", NULL);
perror("grep failed");
}
return 1;
}else{
// wait(&pid);
// fprintf(stderr, "3 - Parentn");
dup2(fd2[0], STDIN_FILENO); //0);
close(fd[0]);
close(fd[1]);
close(fd2[1]);
close(fd2[0]);
execlp("cut", "cut", "-d:", "-f1", NULL);
perror("cut failed");
return 1;
}
return 0;
}