c - 使用 Execvp、fork 和 pipe 的递归管道函数中的错误文件描述符

标签 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);
}

最佳答案

我用这些变化准备了你的函数的变体:

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

生成的程序按我的预期工作:它将指定的命令管道的结果发送到它的标准输出。但是请注意,您的设计本质上仅限于不带任何参数的命令,这严重限制了它的实用性。我的测试用例是 { "ls", "wc"}

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

关于c - 使用 Execvp、fork 和 pipe 的递归管道函数中的错误文件描述符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51987191/

相关文章:

pipe - 如何在管道命令行中使用第一个程序的返回码

c - 当有人使用信号处理输入 "CTRL-C"时,在我的 shell 的历史缓冲区中输出最后 10 个命令

c - C语言进程同步

c - Vim 关键字补全

c - 为什么 C 为这个算法给 Python 不同的值?

c - 在c中逐行读取?

Linux 一对多复用器

c - 使用 Doxygen 在另一个文件中插入功能链接?

c - c 中的 pipe() 和 fork()

java - 通过 JNI 克隆一个带有 POSIX fork 的 JVM,但子 JVM 不会退出