1

このウェブサイトから入手したチュートリアルを使用して、複数のパイプを実装しようとしています。複数のパイプを処理する関数を実行した後、不適切なファイル記述子エラーが発生するようです。初めて複製すると、このエラーが表示されます。コードは次のとおりです。

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* 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);
    }
4

2 に答える 2

2

わかりました、最初に、少し奇妙です - あなたの入れ子は中かっこと一致しません。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);
            }
        }

中括弧を反映するために再インデント:

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

誤解を招く空白で混乱しないように、IDE、エディタ、またはindent(1)コードの実際の構文を反映するようにコードを再インデントするよう依頼してください。

j+=2第二に、以前の反復でを a から変更したと思いますが、j++完全には変更していません。最初の呼び出しでは を使用pipefds[j-2]しており、次の呼び出しでは を使用していますpipefds[j+1]j-1最初の繰り返しで何が起こったのですか?無視されます。これは意図的なものですか?次の反復jでのみ参照されます ( 経由)。の最後から 2 番目のエントリを参照するものはありますか? それもわざと?j+=2 .. [j-2]pipefds[]

于 2011-12-08T09:52:13.133 に答える
0

これが問題の答えです。それが誰かを助けることを願っています。最終的にj2ずつ増やすことにしました(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);
}
于 2011-12-09T01:07:08.263 に答える