我一直在尝试在自己的shell中实现管道,但是有一个我无法修复的错误:
目前,我只管道两个流程。我得到两个命令参数,并将其传递给pipe_launch()
。这是我的pipe_launch()
函数:
int pipe_launch(char** arg1, char** arg2) {
int fd[2], pid;
pipe(fd);
if( (pid = fork()) == 0 ) {
close(1);
dup(fd[1]);
close(fd[0]);
launch(arg1, STDOUT_FILENO, KHOL_FG);
exit(EXIT_FAILURE);
}
else if (pid > 0){
close(0);
dup(fd[0]);
close(fd[1]);
return launch(arg2, STDOUT_FILENO, KHOL_FG);
}
}
供参考,launch()
功能:
int launch(char **args, int fd, int options) {
int khol_bg = 1 ? options & KHOL_BG : 0;
int khol_stdout = 1 ? options & KHOL_STDOUT : 0;
int khol_stderr = 1 ? options & KHOL_STDERR : 0;
int khol_stdin = 1 ? options & KHOL_STDIN : 0;
pid_t pid, wpid;
int status;
if( (pid = fork()) == 0 ) {
// child process
if(fd > 2) {
if(khol_stdout && dup2(fd, STDOUT_FILENO) == -1 ) {
fprintf(stderr, RED "khol: Error duplicating stream: %s\n" RESET, strerror(errno));
return 1;
}
if(khol_stderr && dup2(fd, STDERR_FILENO) == -1 ) {
fprintf(stderr, RED "khol: Error duplicating stream: %s\n" RESET, strerror(errno));
return 1;
}
if(khol_stdin && dup2(fd, STDIN_FILENO) == -1 ) {
fprintf(stderr, RED "khol: Error duplicating stream: %s\n" RESET, strerror(errno));
return 1;
}
close(fd);
}
if( execvp(args[0], args) == -1 ) {
fprintf(stderr, RED "khol: %s\n" RESET, strerror(errno));
}
exit(EXIT_FAILURE);
} else if (pid < 0) {
fprintf(stderr, RED "khol: %s\n" RESET, strerror(errno));
} else {
do {
if( !khol_bg ) {
wpid = waitpid(pid, &status, WUNTRACED);
}
else {
printf(YELLOW "[bg][%d] - %s\n" RESET, pid, args[0]);
}
} while ( !WIFEXITED(status) && !WIFSIGNALED(status) );
}
return 1;
}
现在,当我运行cat sorting | sort
之类的命令时,它会成功执行并显示所需的输出,但在显示下一个提示后,它会自动退出:
/home/sanketdg/projects/khol > cat sorting | sort
12
15
46
78
89
/home/sanketdg/projects/khol > %
%
表示shell已退出。
答案 0 :(得分:1)
你的shell正在关闭它自己的标准输入,并且无法读取任何将来的命令。
else if (pid > 0){
close(0);
(它还为管道的第一部分执行了一个不必要的双叉:设置管道后一个fork()
,然后fork()
中的另一个launch()
。)
pipe()
需要在父shell中执行,但我建议将FD操作推迟到分叉的launch()
子项。不要忘记之后关闭父母的pipe
两个结尾。