【问题标题】:Forking multiple child processes and open()/dup2()分叉多个子进程和 open()/dup2()
【发布时间】:2023-04-04 16:57:01
【问题描述】:

所以我试图读取包含多个命令的行,并为每个命令创建一个子进程来处理它。一旦我尝试取消注释 stdout 重定向 的 if(fd2) 语句,我遇到了一些麻烦。所需的输出不是出现一次,而是出现多次。我不确定是什么原因造成的,我正在关闭所有文件描述符并让子退出。

我正在处理的命令可能同时具有标准输出和标准输入重定向,并且我成功地为标准输入设置了重定向,但我似乎找不到我的错误。我没有收到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),以清除缓冲区,正如另一个问题中所建议的那样,当我为 stdout 调用 open 时,它应该合理地清除缓冲区,但我仍然得到相同的错误.

【问题讨论】:

  • 你应该给minimal reproducible example。一旦我替换了(这里不完整的)execvp 并且当然删除了将转到重定向文件的printf("*STDOUT");,我就无法重现任何问题
  • @AlexHoppus 我继续按照问题中的建议添加了fflush(0)。然而,这并没有解决我最初的问题。

标签: c fork file-descriptor dup2


【解决方案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)

我不知道这是否真的是您的源代码中的拼写错误,或者您只是在发布问题时犯了错误。

【讨论】:

  • 这是我的源代码中的一个错字,它没有解决我最初的问题,但感谢您指出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-28
  • 2021-05-31
相关资源
最近更新 更多