【发布时间】:2017-04-04 15:00:47
【问题描述】:
我一直在尝试在自己的 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 已退出。
【问题讨论】:
-
如果你给出一个更完整的例子(人们可以编译和运行的东西)会有所帮助......但无论如何,在调用
pipe_launch()之后会发生什么?它应该返回什么? -
另外,条件运算符使用
?:...所以,例如。 int khol_bg = 1 ? options & KHOL_BG : 0;可能应该是int khol_bg = (options & KHOL_BG) ? 1 : 0;,对于其他人也是如此。或者只使用int khol_bg = (options & KHOL_BG != 0);甚至int khol_bg = options & KHOL_BG;(对于后者,只有当您不需要完全正确的1时)。 -
并在
printf(YELLOW "[bg][%d] - %s\n" RESET, pid, args[0]);之后的launch()末尾附近添加一个break;,因为在后台情况下status保持未初始化,因此您不能依赖您的do...while条件。