【问题标题】:Implement piping in my own shell在我自己的 shell 中实现管道
【发布时间】: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 &amp; KHOL_BG : 0; 可能应该是 int khol_bg = (options &amp; KHOL_BG) ? 1 : 0;,对于其他人也是如此。或者只使用int khol_bg = (options &amp; KHOL_BG != 0); 甚至int khol_bg = options &amp; KHOL_BG;(对于后者,只有当您不需要完全正确的1 时)。
  • 并在printf(YELLOW "[bg][%d] - %s\n" RESET, pid, args[0]); 之后的launch() 末尾附近添加一个break;,因为在后台情况下status 保持未初始化,因此您不能依赖您的do...while 条件。

标签: c shell fork


【解决方案1】:

您的 shell 正在关闭自己的标准输入,并且无法读取任何未来的命令。

else if (pid > 0){
    close(0);

(它还对管道的第一部分执行了不必要的双分叉:在设置管道后一个fork(),然后在launch() 中另一个fork()。)

pipe() 需要在父 shell 中执行,但我建议将 FD 操作推迟到分叉的launch() 子 shell。不要忘记关闭两个 pipe 结束在父之后。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    相关资源
    最近更新 更多