使用Execvp,Fork和Pipe的递归管道功能中的错误文件描述符

时间:2018-08-23 13:39:16

标签: c pipe fork dup2

我正在尝试使用dup2()fork()pipe()创建递归管道函数。但是,当我的数组类似{"ls", "grep shell"}(其中shell是我的shell的名称)时,它会陷入无尽的循环,显示ls的结果并说“写错误:错误的文件描述符”。我确定某种方式我无法正确终止递归,并且我怀疑问题在于尝试复制fd[1]fd[0],但是在调试了几个小时之后,我仍然找不到出来。任何帮助表示赞赏!

void recursive_piping(char *recursive_pipe_args[MAX_ARGS]) {
    int i = 0;
    int fd[2];

    char *first_arg[2] = {"", NULL};
    char *rest_of_args[81];

    // if its of size 1, base case
    if (recursive_pipe_args[1] == NULL) {
        if (execvp(recursive_pipe_args[0], recursive_pipe_args) == -1) {
            printf("\nExecute didn't work");
            fflush(stdout); 
        }
        return;
    }

    // recursive case, split args into the first on and the rest of them
    first_arg[0] = recursive_pipe_args[0];
    for (i = 0; i < (num_pipes); i++) {
        rest_of_args[i] = malloc(81);
        strcpy(rest_of_args[i], recursive_pipe_args[i+1]);
    }
    if (pipe(fd) < 0) {
        printf("\npipe Failure");
    }

    // parent section, reads file descriptor fd[0]
    if (fork()) {
        close(fd[0]);
        dup2(fd[1], 0);
        recursive_piping(rest_of_args);
        // return;
    }
    close(fd[1]);
    dup2(fd[0], 1);
    execvp(first_arg[0], first_arg);
}

1 个答案:

答案 0 :(得分:0)

我通过以下更改为您的功能做了准备:

  • 它为recursive_pipe_args的第一个元素添加NULL进行检查,在这种情况下,它发出诊断信息而不执行任何操作。
  • 它计算recursive_pipe_args数组中初始非NULL元素的数量,并以该容量动态分配rest_of_args(因此,空间少了一个参数加上NULL标记) 。
  • 它根据前者的实际数量将recursive_pipe_args的尾部复制到rest_of_args中,因此可以肯定地复制了NULL哨兵。
  • 它可以识别并处理fork()中的错误。
  • 它会纠正复制,以便将每个管道(fd[1])的写端复制到标准输出(文件描述符1)上,将读取端复制到标准输入({{ 1}}和fd[0]),并在每个过程中关闭在该过程中未使用的管道末端。
  • 它将错误消息写到标准错误流而不是标准输出中,并尽可能依靠0

生成的程序对我来说是预期的工作:它将指定命令管道的结果发射到其标准输出。但是请注意,您的设计固有地限于不带任何参数的命令,这在很大程度上限制了其实用性。我的测试用例是perror()

实现这些更改的代码留作练习。