Вопрос

I want to set up 2 pipes in my program. I have 1 pipe working fine, but I don't know where to place the second pipe.

The pseudo code of my setup is shown below,

Here is it with curly braces sorry about that

//the first pipe:   
pipe(pipe1) 

//the second pipe:  
pipe(pipe2) 

pid = fork()

if(pid == 0) {

  dup2(pipe1[1], 1)
  close(pipe1[0])
  execvp(beforepipe)
  }  

if(pid > 0) { //everything below is in here

  pid2 = fork()

  if(pid2 == 0){

    //pipe1
    dup2(pipe1[0],0)
    dup2(out,1)
    close(pipe1[1])
    execvp(afterpipe)

    //pipe2 does not work might need to be placed in different area
    dup2(pipe1[1],1)
    close(pipe1[0])
    execvp(beforepipe1)
    }

  if(pid2 > 0){
    close(pipe[0])
    close(pipe[1])
    wait() //this is an infinite for loop

    pid3 = fork()

    if(pid3 == 0){
      dup2(pipe2[0],0)
      dup2(out,1)
      close(pipe2[1])
      execvp(afterpipe2)
      }

    if(pid3 > 0) {
      close(pipe2[0])
      close(pipe2[1])
      wait()
      }
    }

The position of the second pipe is in the wrong place or the code is altogether wrong.

Any suggestions?

Это было полезно?

Решение

Your main problem is that you are not closing anywhere near enough file descriptors. Given a file input1 in the current directory containing your string "eschew obfuscation\", this code works for me (but note how many file descriptors have to be closed!).

  • Rule of thumb: if a pipe is dup2()d or dup()d to standard input or output, close both file pipe file descriptors.

Example code (with debug tracing in place):

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

/* command pipeline: cat input1 | tr a-z A-Z | tr \\ q */

int main(void)
{
    int pipe1[2];
    int pipe2[2];
    pid_t pid1;
    char *cmd1[] = { "cat", "input1",        0 };
    char *cmd2[] = { "tr",  "a-z",    "A-Z", 0 };
    char *cmd3[] = { "tr",  "\\",     "q",   0 };

    if (pipe(pipe1) != 0 || pipe(pipe2) != 0)
    {
        perror("pipe failed");
        return 1;
    }

    pid1 = fork();

    if (pid1 < 0)
    {
        perror("fork 1 failed");
        return 1;
    }

    if (pid1 == 0)
    {
        /* Child 1 - cat */
        dup2(pipe1[1], 1);
        close(pipe1[0]);
        close(pipe1[1]);
        close(pipe2[0]);
        close(pipe2[1]);
        execvp(cmd1[0], cmd1);
        perror("failed to execute cmd1");
        return 1;
    }

    printf("pid 1 = %d\n", pid1);
    fflush(stdout);

    pid_t pid2 = fork();
    if (pid2 < 0)
    {
        perror("fork 2 failed");
        return 1;
    }

    if (pid2 == 0)
    {
        /* Child 2 - tr a-z A-Z */
        dup2(pipe1[0], 0);
        dup2(pipe2[1], 1);
        close(pipe1[0]);
        close(pipe1[1]);
        close(pipe2[0]);
        close(pipe2[1]);
        execvp(cmd2[0], cmd2);
        perror("failed to execute cmd2");
        return 1;
    }

    printf("pid 2 = %d\n", pid2);
    fflush(stdout);

    pid_t pid3 = fork();
    if (pid3 < 0)
    {
        perror("fork 3 failed");
        return 1;
    }

    if (pid3 == 0)
    {
        /* Child 3 - tr \\ q */
        dup2(pipe2[0], 0);
        close(pipe1[0]);
        close(pipe1[1]);
        close(pipe2[0]);
        close(pipe2[1]);
        execvp(cmd3[0], cmd3);
        perror("failed to execute cmd3");
        return 1;
    }

    printf("pid 3 = %d\n", pid3);
    fflush(stdout);

    /* Parent - wait for the kids to all die */
    close(pipe1[0]);
    close(pipe1[1]);
    close(pipe2[0]);
    close(pipe2[1]);

    pid_t corpse;
    int   status;
    while ((corpse = wait(&status)) > 0)
        printf("Child %d died status 0x%.4X\n", corpse, status);

    return 0;
}

Другие советы

execvp(afterpipe)
//pipe2 does not work might need to be placed in different area
dup2(pipe1[1],1)
close(pipe1[0])
execvp(beforepipe1)

I think the execvp() didnot return. So the code below the execvp() is irrelevent.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top