C dup2错误的文件描述符错误

C dup2错误的文件描述符错误,c,linux,shell,pipe,dup2,C,Linux,Shell,Pipe,Dup2,我正在尝试使用从本教程中获得的教程来实现多个管道。在执行处理多个管道的函数后,我似乎遇到了一个错误的文件描述符错误。当我第一次复制时,它会向我发送此错误。代码如下: void runPipedCommands(cmdLine* command, char* userInput) { int numPipes = countPipes(userInput); int status = 0; int i = 0, j = 0; pid_t pid; in

我正在尝试使用从本教程中获得的教程来实现多个管道。在执行处理多个管道的函数后,我似乎遇到了一个错误的文件描述符错误。当我第一次复制时,它会向我发送此错误。代码如下:

void runPipedCommands(cmdLine* command, char* userInput) {
    int numPipes = countPipes(userInput);

    int status = 0;
    int i = 0, j = 0;

    pid_t pid;

    int pipefds[2*numPipes];

    for(i = 0; i < (numPipes); i++){
        if(pipe(pipefds + i*2) < 0) {
            perror("pipe");
            exit(EXIT_FAILURE);
        }
    }

    j = 0;
    while(command) {
        pid = fork();
        if(pid == 0) {

            //if not first command
            if(j != 0){
                if(dup2(pipefds[j-2], 0) < 0){
                    perror(" dup2");///j-2 0 j+1 1
                    exit(EXIT_FAILURE);

                }

            if(command->next){
                printf(
                if(dup2(pipefds[j + 1], 1) < 0){
                    perror("dup2");
                    exit(EXIT_FAILURE);
                }
            }

            for(i = 0; i < 2*numPipes; i++){
                    close(pipefds[i]);
            }

            if( execvp(*command->arguments, command->arguments) < 0 ){
                    perror(*command->arguments);
                    exit(EXIT_FAILURE);
            }
        } else if(pid < 0){
            perror("error");
            exit(EXIT_FAILURE);
        }

        command = command->next;
        j++;
    }
        for(i = 0; i < 2 * numPipes; i++){
            close(pipefds[i]);
            printf("in parent: closed pipe[%d]\n", i);
        }
        wait(0);
    }
}
void runPipedCommands(cmdLine*命令,char*用户输入){
int numPipes=countPipes(用户输入);
int status=0;
int i=0,j=0;
pid_t pid;
内部管道[2*numPipes];
对于(i=0;i<(numPipes);i++){
如果(管道(管道FDS+i*2)<0){
佩罗(“管道”);
退出(退出失败);
}
}
j=0;
while(命令){
pid=fork();
如果(pid==0){
//如果不是第一个命令
如果(j!=0){
if(dup2(pipefds[j-2],0)<0){
perror(“dup2”);///j-20j+11
退出(退出失败);
}
如果(命令->下一步){
printf(
if(dup2(pipefds[j+1],1)<0){
perror(“dup2”);
退出(退出失败);
}
}
对于(i=0;i<2*numPipes;i++){
关闭(管道[i]);
}
if(execvp(*命令->参数,命令->参数)<0){
perror(*命令->参数);
退出(退出失败);
}
}否则如果(pid<0){
佩罗(“错误”);
退出(退出失败);
}
命令=命令->下一步;
j++;
}
对于(i=0;i<2*numPipes;i++){
关闭(管道[i]);
printf(“在父级中:封闭管道[%d]\n”,i);
}
等待(0);
}
}
可能某个地方有泄漏,或者找不到描述符。我似乎不知道问题出在哪里。我做错了什么?谢谢

编辑代码:

void runPipedCommands(cmdLine* command, char* userInput) {
    int numPipes = countPipes(userInput);

    int status = 0;
    int i = 0, j = 0;

    pid_t pid;

    int pipefds[2*numPipes];

    for(i = 0; i < (numPipes); i++){
        if(pipe(pipefds + i*2) < 0) {
            perror("pipe");
            exit(EXIT_FAILURE);
        }
    }

    j = 0;
    while(command) {
        pid = fork();
        if(pid == 0) {
            //if not first command
            if(j != 0 && j!= 2*numPipes){
                if(dup2(pipefds[j-2], 0) < 0){
                    perror(" dup2");///j-2 0 j+1 1
                    exit(EXIT_FAILURE);

                }
            }

            //if not last command
            if(command->next){
                printf("command exists: dup(pipefd[%d], 1])\n", j+1);
                if(dup2(pipefds[j + 1], 1) < 0){
                    perror("dup2");
                    exit(EXIT_FAILURE);
                }
            }

            for(i = 0; i < 2*numPipes; i++){
                    close(pipefds[i]);
                   printf("in child: closed pipe[%d]\n", i);
            }

            if( execvp(*command->arguments, command->arguments) < 0 ){
                    perror(*command->arguments);
                    exit(EXIT_FAILURE);
            }
        } else if(pid < 0){
            perror("error");
            exit(EXIT_FAILURE);
        }

        command = command->next;
        j+=2;
    }
        for(i = 0; i < 2 * numPipes; i++){
            close(pipefds[i]);
            printf("in parent: closed pipe[%d]\n", i);
        }   
           wait(0);
    }
void runPipedCommands(cmdLine*命令,char*用户输入){
int numPipes=countPipes(用户输入);
int status=0;
int i=0,j=0;
pid_t pid;
内部管道[2*numPipes];
对于(i=0;i<(numPipes);i++){
如果(管道(管道FDS+i*2)<0){
佩罗(“管道”);
退出(退出失败);
}
}
j=0;
while(命令){
pid=fork();
如果(pid==0){
//如果不是第一个命令
如果(j!=0&&j!=2*numPipes){
if(dup2(pipefds[j-2],0)<0){
perror(“dup2”);///j-20j+11
退出(退出失败);
}
}
//如果不是最后一个命令
如果(命令->下一步){
printf(“命令存在:dup(pipefd[%d],1])\n”,j+1);
if(dup2(pipefds[j+1],1)<0){
perror(“dup2”);
退出(退出失败);
}
}
对于(i=0;i<2*numPipes;i++){
关闭(管道[i]);
printf(“在子系统中:封闭管道[%d]\n”,i);
}
if(execvp(*命令->参数,命令->参数)<0){
perror(*命令->参数);
退出(退出失败);
}
}否则如果(pid<0){
佩罗(“错误”);
退出(退出失败);
}
命令=命令->下一步;
j+=2;
}
对于(i=0;i<2*numPipes;i++){
关闭(管道[i]);
printf(“在父级中:封闭管道[%d]\n”,i);
}   
等待(0);
}

好的,首先,有一点奇怪——你的嵌套没有与大括号对齐。
if(j!=0)
if(command->next)
看起来像是相同的“级别”,但实际的大括号讲述了不同的故事:

复制和粘贴:

        if(j != 0){
            if(dup2(pipefds[j-2], 0) < 0){
                perror(" dup2");///j-2 0 j+1 1
                exit(EXIT_FAILURE);
            }

        if(command->next){
            printf(
            if(dup2(pipefds[j + 1], 1) < 0){
                perror("dup2");
                exit(EXIT_FAILURE);
            }
        }
如果(j!=0){
if(dup2(pipefds[j-2],0)<0){
perror(“dup2”);///j-20j+11
退出(退出失败);
}
如果(命令->下一步){
printf(
if(dup2(pipefds[j+1],1)<0){
perror(“dup2”);
退出(退出失败);
}
}
重新缩进以反映大括号:

if (j != 0) {
    if (dup2(pipefds[j - 2], 0) < 0) {
        perror(" dup2");    ///j-2 0 j+1 1
        exit(EXIT_FAILURE);
    }

    if (command->next) {
        printf(); /* fixed this */
        if (dup2(pipefds[j + 1], 1) < 0) {
            perror("dup2");
            exit(EXIT_FAILURE);
        }
    }
}
如果(j!=0){
if(dup2(pipefds[j-2],0)<0){
perror(“dup2”);///j-20j+11
退出(退出失败);
}
如果(命令->下一步){
printf();/*修复了此问题*/
if(dup2(pipefds[j+1],1)<0){
perror(“dup2”);
退出(退出失败);
}
}
}
请让您的IDE、编辑器或缩进(1)重新缩进代码以反映代码的实际语法,这样您就不会被误导性的空白所迷惑


其次,我认为您在早期迭代中将
j++
j++
更改为
j+=2
,但并没有完全这样做——在第一次调用中,您使用的是
pipefds[j-2]
,在下一次调用中,您使用的是
pipefds[j+1]
j-1在第一次迭代中发生了什么?它被忽略。这是故意的吗?
j
只在下一次迭代中被引用(通过
j+=2..[j-2]
)。有什么会引用
pipefds[]中的下一个到最后一个条目吗
?这也是故意的吗?

这是问题的答案。希望它能帮助其他人。我最终决定将
j
增加2
(j+=2)
。函数
countPipes(char*)
只是一个简单的函数,可以从
char*
计算管道的数量

void runPipedCommands(cmdLine* command, char* userInput) {
    int numPipes = countPipes(userInput);

    int status;
    int i = 0;
    pid_t pid;

    int pipefds[2*numPipes];//declare pipes

    /**Set up pipes*/
    for(i = 0; i < (numPipes); i++){
        if(pipe(pipefds + i*2) < 0) {
            perror("couldn't pipe");
            exit(EXIT_FAILURE);
        }
    }

    int j = 0;
    while(command) {
        pid = fork();
        if(pid == 0) {

            //if not last command
            if(command->next){
                if(dup2(pipefds[j + 1], 1) < 0){
                    perror("dup2");
                    exit(EXIT_FAILURE);
                }
            }

            //if not first command
            if(j != 0 ){
                if(dup2(pipefds[j-2], 0) < 0){
                    perror(" dup2");///j-2 0 j+1 1
                    exit(EXIT_FAILURE);

                }
            }

            //close pipes in child
            for(i = 0; i < 2*numPipes; i++){
                    close(pipefds[i]);
            }

            //execute commands
            if( execvp(*command->arguments, command->arguments) < 0 ){
                    perror(*command->arguments);
                    exit(EXIT_FAILURE);
            }
        } else if(pid < 0){
            perror("error");
            exit(EXIT_FAILURE);
        }

        command = command->next;//go to the next command in the linked list
        j+=2;//increment j
    }

    /**Parent closes the pipes and waits for all of its children*/

    for(i = 0; i < 2 * numPipes; i++){
        close(pipefds[i]);
    }

    for(i = 0; i < numPipes + 1; i++) //parent waits for all of its children
        wait(&status);
}
void runPipedCommands(cmdLine*命令,char*用户输入){
int numPipes=countPipes(用户输入);
智力状态;
int i=0;
pid_t pid;
int pipefds[2*numPipes];//声明管道
/**架设管道*/
对于(i=0;i<(numPipes);i++){
如果(管道(管道FDS+i*2)<0){
佩罗尔(“不会吹管”);
退出(退出失败);
}
}
int j=0;
while(命令){
pid=fork();
如果(pid==0){
//如果