Разветвление нескольких дочерних процессов и open()/dup2()

Итак, я пытаюсь прочитать строку с несколькими командами и создать дочерний процесс для каждой команды для ее обработки. У меня возникли проблемы при попытке раскомментировать оператор if(fd2) для перенаправления stdout. Вместо того, чтобы желаемый вывод отображался один раз, он появляется несколько раз. Я не совсем уверен, что вызывает это, я закрываю все дескрипторы файлов и завершаю дочерний процесс.

Команды, с которыми я имею дело, могут иметь перенаправление как на стандартный вывод, так и на стандартный ввод, и мне удалось настроить перенаправление для стандартного ввода, но я не могу найти свою ошибку. У меня не отображается предупреждение perror(). Это не столько проблема с dup2(), сколько с open(), если я просто раскомментирую эту часть, я получаю ошибку.

int concCmd(Cmd cmdM[], int iCmdCnt, Token tokenM[], int iTokenCnt){
   long pid, wpid;
   int i, status=0, fd = 0, fd2=0;
   fflush(0);
   for(i=0; i<iCmdCnt; i++){ //create a process for every command
        pid=fork();
        switch(pid){
            case -1:
                perror("Fork\n");
                return 1;
            case 0:
                if(cmdM[i].iStdinRedirectIdx != 0){ //does command need stdin redirection
                    if((fd = open(tokenM[cmdM[i].iStdinRedirectIdx], O_RDONLY)) <0){
                        perror("open stdin");
                        return 1;
                    }
                    if((dup2(fd,STDIN_FILENO))<0){
                        perror("dup2");
                        return 1;
                    }
                    close(fd); //close in parent process
                }
                if(cmdM[i].iStdoutRedirectIdx != 0){ //command needs stdout redirection
                //   if((fd2 = open(tokenM[cmdM[i].iStdoutRedirectIdx], O_WRONLY|O_CREAT|O_EXCL)) < 0){
                //        perror("open stdout");
                //        return 1;
                //    }
                //    if((dup2(fd, STDOUT_FILENO))<0){
                //        perror("dup2");
                //        return 1;
                //    }
                    close(fd2);
                }
                //EXECVP HERE!!!
                //execvp (cmdM[i].szCmdNm, tokenM[
                exit(0);
            default:
                wpid = wait(&status);
                close(fd);
                close(fd2);
                fprintf(stderr, "%ld %ld\n", (long)getpid(), wpid);
        }
    }
    return 0;
}

Я пошел дальше и добавил fflush(0), прежде чем начать разветвление, чтобы очистить буфер, как это было предложено в другом вопросе, который должен разумно очищать буфер, когда я вызываю open для stdout, но я все еще получаю те же ошибки.


person JOhAnn4187    schedule 30.11.2017    source источник
comment
Возможный дубликат аномалии printf после fork()   -  person Alex Hoppus    schedule 30.11.2017
comment
Вы должны привести минимально воспроизводимый пример. Я не могу воспроизвести какую-либо проблему после того, как заменил (здесь неполный) execvp и, конечно же, удалил printf("*STDOUT");, который попадет в перенаправленный файл.   -  person Serge Ballesta    schedule 30.11.2017
comment
@AlexHoppus Я пошел дальше и добавил fflush(0), как было предложено в вопросе. Однако это не решило мою первоначальную проблему.   -  person JOhAnn4187    schedule 30.11.2017


Ответы (1)


Я собирался сделать комментарий, потому что то, что я хочу сказать, очень просто, но мне нужно сослаться на какой-то код, поэтому, возможно, опубликовать ответ будет проще.

        //   if((fd2 = open(tokenM[cmdM[i].iStdoutRedirectIdx], O_WRONLY|O_CREAT|O_EXCL)) < 0){
        //        perror("open stdout");
        //        return 1;
        //    }
        //    if((dup2(fd, STDOUT_FILENO))<0){
        //        perror("dup2");
        //        return 1;
        //    }

В вашем коде часть о fd2, которую вы комментируете в своем вопросе, содержит опечатку.

dup2(fd, STDOUT_FILENO) должно быть dup2(fd2, STDOUT_FILENO)

Я не знаю, действительно ли это опечатка в вашем исходном коде, или вы просто допустили ошибку, когда задавали свой вопрос.

person Bruce    schedule 30.11.2017
comment
Это была опечатка в моем исходном коде, она не разрешила мой первоначальный вопрос, но спасибо, что указали на это. - person JOhAnn4187; 30.11.2017