Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Execvp、fork和pipe的递归管道函数中存在错误的文件描述符_C_Pipe_Fork_Dup2 - Fatal编程技术网

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

使用Execvp、fork和pipe的递归管道函数中存在错误的文件描述符,c,pipe,fork,dup2,C,Pipe,Fork,Dup2,我正在尝试使用dup2()、fork()和pipe()创建递归管道函数。但是,当我的数组类似于{“ls”,“grepshell”}(其中shell是我的shell的名称)时,它会进入一个无休止的循环,显示ls的结果并说“write error:bad file descriptor”。我确信我没有正确地终止我的递归,我怀疑问题在于尝试重复fd[1]或fd[0],但在调试了几个小时后,我仍然无法找到它。感谢您的帮助 void recursive_piping(char *recursive_pip

我正在尝试使用
dup2()
fork()
pipe()
创建递归管道函数。但是,当我的数组类似于
{“ls”,“grepshell”}
(其中shell是我的shell的名称)时,它会进入一个无休止的循环,显示ls的结果并说“write error:bad file descriptor”。我确信我没有正确地终止我的递归,我怀疑问题在于尝试重复
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);
}
无效递归管道(字符*递归管道参数[最大参数]){
int i=0;
int-fd[2];
char*first_arg[2]={“”,NULL};
字符*参数的剩余部分[81];
//如果其大小为1,则为基本情况
if(递归管道参数[1]==NULL){
if(execvp(递归管道参数[0],递归管道参数)=-1){
printf(“\nExecute不起作用”);
fflush(stdout);
}
返回;
}
//递归情况下,将arg拆分为第一个on和其余的
第一个参数[0]=递归管道参数[0];
对于(i=0;i<(管道数);i++){
剩余的参数[i]=malloc(81);
strcpy(剩余参数[i],递归参数[i+1]);
}
如果(管道(fd)<0){
printf(“\n管道故障”);
}
//父节,读取文件描述符fd[0]
if(fork()){
关闭(fd[0]);
dup2(fd[1],0);
递归管道(其余参数);
//返回;
}
关闭(fd[1]);
dup2(fd[0],1);
execvp(第一个参数[0],第一个参数);
}

我用这些更改为您的函数准备了一个变体

  • 它为
    recursive\u pipe\u args
    的第一个元素
    NULL
    添加了一个检查,在这种情况下,它会在不执行任何操作的情况下发出诊断
  • 它统计
    recursive\u pipe\u args
    数组中初始非空元素的数量,并动态分配
    rest\u个具有该容量的\u args
    (从而允许一个更少的参数加上
    NULL
    哨兵的空间)
  • 它根据前者元素的实际计数,将递归参数的尾部复制到参数的剩余部分,从而确保复制
    NULL
    哨兵
  • 它识别并处理
    fork()
    中的错误
  • 它更正复制,以便将每个管道的写入端(
    fd[1]
    )复制到标准输出(文件描述符
    1
    ),将读取端复制到标准输入端(
    fd[0]
    0
    ),并在每个进程中关闭该进程中未使用的管道端
  • 它将错误消息写入标准错误流而不是标准输出,并尽可能依赖
    peror()
结果程序的工作方式与我预期的一样:它将指定命令管道的结果发送到其标准输出。但是,请注意,您的设计本质上局限于没有任何参数的命令,这严重限制了它的实用性。我的测试用例是
{“ls”,“wc”}


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

if(fork())…Ouch。你想过如果
fork()
失败会发生什么吗?啊,说实话,不是真的。什么是
num_pipes
?你正在
将管道的读取端复制到预期用于输出的文件描述符上,反之亦然。这可能是“错误的文件描述符”错误的根本原因。是的,@Roug,当您通过shell执行该命令时,shell会将“grep shell”解析为命令名“grep”和一个参数“shell”。这是在shell中实现的,而不是在底层exec调用中实现的。