如何在子进程中正确使用管道? //我想执行pwd | sort>file.txt char命令[2][30]={“pwd”,“sort”}; char目录[2][30]={/usr/bin/pwd“,“/usr/bin/sort”} char outputFile[30]=“file.txt” inttotalcommands=2; bool isOutputFilePresent=真; //创建两个管道 int-fd1[2]; int-fd2[2]; 管道(fd1); 管道(fd2); //关闭写入端但保持读取端打开,因为关闭它们会破坏两个管道 关闭(fd1[1]); 关闭(fd2[1]); //循环,通过在每次迭代中创建子进程来执行每个命令 对于(int i=0;i0) 写入(STDOUT_文件号和buf,1); 写入(标准输出文件号,“\n”,1); 关闭(pipefd[0]); _退出(退出成功); }else{/*父对象将argv[1]写入管道*/ 关闭(pipefd[0]);/*关闭未使用的读取端*/ 写入(pipefd[1],argv[1],strlen(argv[1]); 关闭(pipefd[1]);/*读卡器将看到EOF*/ 等待(NULL);/*等待子项*/ 退出(退出成功); } } 如果我们关闭管道的一端并调用fork,子进程是否也会将其作为关闭的文件继承?请自己尝试并查看:)(我相信答案是子进程继承打开的文件句柄。关闭的文件句柄不会重新打开。) #include <sys/types.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> int main(int argc, char *argv[]) { int pipefd[2]; pid_t cpid; char buf; if (argc != 2) { fprintf(stderr, "Usage: %s <string>\n", argv[0]); exit(EXIT_FAILURE); } if (pipe(pipefd) == -1) { perror("pipe"); exit(EXIT_FAILURE); } cpid = fork(); if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (cpid == 0) { /* Child reads from pipe */ close(pipefd[1]); /* Close unused write end */ while (read(pipefd[0], &buf, 1) > 0) write(STDOUT_FILENO, &buf, 1); write(STDOUT_FILENO, "\n", 1); close(pipefd[0]); _exit(EXIT_SUCCESS); } else { /* Parent writes argv[1] to pipe */ close(pipefd[0]); /* Close unused read end */ write(pipefd[1], argv[1], strlen(argv[1])); close(pipefd[1]); /* Reader will see EOF */ wait(NULL); /* Wait for child */ exit(EXIT_SUCCESS); } }

如何在子进程中正确使用管道? //我想执行pwd | sort>file.txt char命令[2][30]={“pwd”,“sort”}; char目录[2][30]={/usr/bin/pwd“,“/usr/bin/sort”} char outputFile[30]=“file.txt” inttotalcommands=2; bool isOutputFilePresent=真; //创建两个管道 int-fd1[2]; int-fd2[2]; 管道(fd1); 管道(fd2); //关闭写入端但保持读取端打开,因为关闭它们会破坏两个管道 关闭(fd1[1]); 关闭(fd2[1]); //循环,通过在每次迭代中创建子进程来执行每个命令 对于(int i=0;i0) 写入(STDOUT_文件号和buf,1); 写入(标准输出文件号,“\n”,1); 关闭(pipefd[0]); _退出(退出成功); }else{/*父对象将argv[1]写入管道*/ 关闭(pipefd[0]);/*关闭未使用的读取端*/ 写入(pipefd[1],argv[1],strlen(argv[1]); 关闭(pipefd[1]);/*读卡器将看到EOF*/ 等待(NULL);/*等待子项*/ 退出(退出成功); } } 如果我们关闭管道的一端并调用fork,子进程是否也会将其作为关闭的文件继承?请自己尝试并查看:)(我相信答案是子进程继承打开的文件句柄。关闭的文件句柄不会重新打开。) #include <sys/types.h> #include <sys/wait.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> int main(int argc, char *argv[]) { int pipefd[2]; pid_t cpid; char buf; if (argc != 2) { fprintf(stderr, "Usage: %s <string>\n", argv[0]); exit(EXIT_FAILURE); } if (pipe(pipefd) == -1) { perror("pipe"); exit(EXIT_FAILURE); } cpid = fork(); if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); } if (cpid == 0) { /* Child reads from pipe */ close(pipefd[1]); /* Close unused write end */ while (read(pipefd[0], &buf, 1) > 0) write(STDOUT_FILENO, &buf, 1); write(STDOUT_FILENO, "\n", 1); close(pipefd[0]); _exit(EXIT_SUCCESS); } else { /* Parent writes argv[1] to pipe */ close(pipefd[0]); /* Close unused read end */ write(pipefd[1], argv[1], strlen(argv[1])); close(pipefd[1]); /* Reader will see EOF */ wait(NULL); /* Wait for child */ exit(EXIT_SUCCESS); } },c,pipe,unistd.h,C,Pipe,Unistd.h,由于子进程将继承其自己的管道FDs,因此我关闭了每个进程中未使用的管道,并使用dup2将stdout和stdin FDs分配给它。但是这段代码有一个逻辑错误,我想这是因为没有正确使用管道。那么,我在管道的概念上犯了什么错误?这个问题的解决方案是什么。谢谢 打开管道后,立即关闭管道的写入端。因此,任何东西都无法写入这些管道: //I want to execute pwd|sort > file.txt char commands[2][30] = {"pwd", &q

由于子进程将继承其自己的管道FDs,因此我关闭了每个进程中未使用的管道,并使用dup2将stdout和stdin FDs分配给它。但是这段代码有一个逻辑错误,我想这是因为没有正确使用管道。那么,我在管道的概念上犯了什么错误?这个问题的解决方案是什么。谢谢

打开管道后,立即关闭管道的写入端。因此,任何东西都无法写入这些管道:

//I want to execute pwd|sort > file.txt

char commands[2][30] = {"pwd", "sort"};
char directory [2][30] = {"/usr/bin/pwd", "/usr/bin/sort"}
char outputFile[30] = "file.txt"
int totalCommands = 2;
bool isOutputFilePresent = true;

//creating two pipes
int fd1[2];
int fd2[2];
pipe(fd1);
pipe(fd2);
//Closing the writing ends but keeping the reading ends open as closing them will destroy both the pipes
close (fd1[1]);
close (fd2[1]);

//loop to execute each command by creating a child process in each iteration
for (int i = 0; i < totalCommands; ++i)
{
    pid_t pid = fork();
    if (pid == 0)
    {
        if (i == totalCommands - 1)
        {
            if (i%2 == 0)
            {
                close(fd1[1]);
                close(fd2[0]);
                dup2(fd1[0], 0);
                dup2(fd2[1], 1);
            }
            else
            {
                close(fd2[1]);
                close(fd1[0]);
                dup2(fd2[0], 0);
                dup2(fd1[1], 1);
            }
        }
        else
        {
            if (i%2 == 0)
            { 
                close(fd2[0]);
                close(fd2[1]);
                close(fd1[1]);
                dup2(fd1[0], 0);
            }
            else
            {
                close(fd1[0]);
                close(fd1[1]);
                close(fd2[1]);
                dup2(fd2[0], 0);
            }
            if(isOutputFilePresent)
            {
                int outputFD = open (outputFile, O_WRONLY | O_CREAT);
                dup2(outputFD, 1);
            }

        }
        execv(directory[i], commands[i]) //ignore the fact that i am passing command name instead of argument vector
    }
    wait(NULL);
}

这样做:

  • 创建两个管道:A和B
  • Fork/spawn新子进程
  • 父级关闭A的写入端和B的读取端
  • 子级关闭A的读取端和B的写入端
  • 因此,子对象向A写入,父对象从A读取。 父级写入B,子级读取B

    管道(2)的示例代码向您展示了如何执行此操作:

    pipe(fd1);
    pipe(fd2);
    //Closing the writing ends but keeping the reading ends open as closing them will destroy both the pipes
    close (fd1[1]);
    close (fd2[1]);
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    int
    main(int argc,char*argv[])
    {
    int-pipefd[2];
    pid_t cpid;
    焦炉;
    如果(argc!=2){
    fprintf(stderr,“用法:%s\n”,argv[0]);
    退出(退出失败);
    }
    如果(管道(管道FD)=-1){
    佩罗(“管道”);
    退出(退出失败);
    }
    cpid=fork();
    如果(cpid==-1){
    佩罗尔(“福克”);
    退出(退出失败);
    }
    如果(cpid==0){/*子级从管道读取*/
    关闭(pipefd[1]);/*关闭未使用的写入端*/
    while(读取(pipefd[0],&buf,1)>0)
    写入(STDOUT_文件号和buf,1);
    写入(标准输出文件号,“\n”,1);
    关闭(pipefd[0]);
    _退出(退出成功);
    }else{/*父对象将argv[1]写入管道*/
    关闭(pipefd[0]);/*关闭未使用的读取端*/
    写入(pipefd[1],argv[1],strlen(argv[1]);
    关闭(pipefd[1]);/*读卡器将看到EOF*/
    等待(NULL);/*等待子项*/
    退出(退出成功);
    }
    }
    
    如果我们关闭管道的一端并调用fork,子进程是否也会将其作为关闭的文件继承?请自己尝试并查看:)(我相信答案是子进程继承打开的文件句柄。关闭的文件句柄不会重新打开。)
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    
    int
    main(int argc, char *argv[])
    {
       int pipefd[2];
       pid_t cpid;
       char buf;
    
       if (argc != 2) {
           fprintf(stderr, "Usage: %s <string>\n", argv[0]);
           exit(EXIT_FAILURE);
       }
    
       if (pipe(pipefd) == -1) {
           perror("pipe");
           exit(EXIT_FAILURE);
       }
    
       cpid = fork();
       if (cpid == -1) {
           perror("fork");
           exit(EXIT_FAILURE);
       }
    
       if (cpid == 0) {    /* Child reads from pipe */
           close(pipefd[1]);          /* Close unused write end */
    
           while (read(pipefd[0], &buf, 1) > 0)
               write(STDOUT_FILENO, &buf, 1);
    
           write(STDOUT_FILENO, "\n", 1);
           close(pipefd[0]);
           _exit(EXIT_SUCCESS);
    
       } else {            /* Parent writes argv[1] to pipe */
           close(pipefd[0]);          /* Close unused read end */
           write(pipefd[1], argv[1], strlen(argv[1]));
           close(pipefd[1]);          /* Reader will see EOF */
           wait(NULL);                /* Wait for child */
           exit(EXIT_SUCCESS);
       }
    }