简体   繁体   English

如何在子进程中正确使用管道?

[英]How to use pipes correctly with child processes?

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

As the child process will inherit its own FDs of the pipe, I closed unused pipes in each process and by using dup2, assigned stdout and stdin FDs to it.由于子进程将继承其自己的 pipe FD,因此我关闭了每个进程中未使用的管道,并使用 dup2 为其分配了 stdout 和 stdin FD。 But this code has a logical error and I guess its because of not using the pipes correctly.但是这段代码有一个逻辑错误,我猜是因为没有正确使用管道。 So where am I mistaken in the concept of pipes and what could be the solution to this problem.那么我在管道的概念上哪里弄错了,这个问题的解决方案是什么。 Thanks!谢谢!

You close the write end of the pipes immediately after opening them.打开管道后立即关闭管道的写入端。 Therefore nothing can write to those pipes:因此,没有任何东西可以写入这些管道:

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

Do this:做这个:

  1. Create two pipes: A and B创建两个管道:A 和 B
  2. Fork/spawn new child process分叉/生成新的子进程
  3. Parent closes write-end of A and read-end of B父关闭 A 的写端和 B 的读端
  4. Child closes read-end of A and write-end of B Child 关闭 A 的读端和 B 的写端

Thus the child writes to A, and the parent reads from A. The parent writes to B, and the child reads from B.因此,孩子向 A 写入,父母从 A 读取。父母向 B 写入,孩子从 B 读取。

The man page for pipe(2) give you example code that shows you how to do this: pipe(2) 的手册页为您提供了示例代码,向您展示了如何执行此操作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM