gtpc2m5dC/C++ Language Support User's Guide

pipe-Create an Unnamed Pipe

This function creates a pipe, which is an input/output (I/O) channel that one or more processes can use to communicate with each other or, in some cases, that a process can use to communicate with itself.

Data is written into one end of the pipe and read from the other.

Format

#include <unistd.h>
int pipe(int fdinfo[2]);

fdinfo
The fdinfo parameter points to an array of 2 integers where the pipe function stores two file descriptors.

Normal Return

If successful, the pipe function returns a zero value. A file descriptor for the read end of the pipe is stored in the fdinfo[0] parameter and a file descriptor for the write end of the pipe is stored in the fdinfo[1] parameter.

Error Return

If unsuccessful, the pipe function returns a value of -1 and sets errno to one of the following:

EMFILE
The process has already reached its maximum number of open file descriptors. This limit is given by OPEN_MAX, which is defined in the limits.h header file.

ENOMEM
There is not enough storage space available.

Programming Considerations

Examples

The following example consists of two programs that calculate and write the first 20 numbers in the Fibonacci sequence, which is a sequence of numbers where each number is the sum of the 2 preceding numbers.

Program 1 is a simple program that reads 2 integers, adds the integers, and writes the sum.

Program 2 opens two pipes that are used to communicate with program 1, which is created as a new child process using the tpf_fork function. For the child process, the read end of one pipe is set as standard input (stdin) and the write end of the other pipe is set as standard output (stdout).

The two processes communicate by using the two pipes to calculate the first 20 numbers in the Fibonacci sequence.

The following sequence is the result of the processing of these two programs:

1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765

Program 1:

/**********************************************************************/
/* A simple integer adder.                                            */
/**********************************************************************/
#include <stdio.h>
 
int main(void)
{
    int i1, i2;
 
    /******************************************************************/
    /* Read two numbers from stdin.                                   */
    /******************************************************************/
    while (scanf("%d%d", &i1, &i2) == 2)
    {
        /**************************************************************/
        /* Write their sum to stdout.                                 */
        /**************************************************************/
        printf("%d\n", i1 + i2);
        fflush(stdout);
    }
    return 0;
}

Program 2:

/**********************************************************************/
/* This program calls the simple integer adder program to calculate   */
/* the first 20 numbers in the fibonacci series.                      */
/**********************************************************************/
#define _POSIX_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sysapi.h>
 
#define SERIES_COUNT 20
 
int main(int argc, char **argv)
{
    FILE *original_stdout;
    int pipe1[2], pipe2[2];
    FILE *write_to_adder, *read_from_adder;
 
    {
        /**************************************************************/
        /* Copy the original stdout.  We'll use its file descriptor   */
        /* for the child process' stdout.                             */
        /**************************************************************/
        int stdout_copy = dup(STDOUT_FILENO);   /* file descriptor 3 */
        original_stdout = fdopen(stdout_copy, "w");
        fcntl(stdout_copy, F_SETFD,
              FD_CLOEXEC | fcntl(stdout_copy, F_GETFD));
    }
 
    /******************************************************************/
    /* Close file descriptors 0 and 1.  We will use them for the      */
    /* child process' stdin and stdout.                               */
    /******************************************************************/
    fclose(stdin);  /* file descriptor 0 */
    fclose(stdout); /* file descriptor 1 */
 
    /******************************************************************/
    /* The first pipe() function call opens file descriptors 0 and 1. */
    /* We will duplicate and close 0 for the parent to read from the  */
    /* child process; 1 will be the child process' stdout.            */
    /******************************************************************/
    pipe(pipe1);    /* file descriptors 0 and 1 */
    {
        int read_end_copy = dup(pipe1[0]);  /* file descriptor 4 */
        close(pipe1[0]);    /* file descriptor 0 */
        read_from_adder = fdopen(read_end_copy, "r");
        fcntl(read_end_copy, F_SETFD,
              FD_CLOEXEC | fcntl(read_end_copy, F_GETFD));
    }
 
    /******************************************************************/
    /* The second pipe() function call opens file descriptors 0 and   */
    /* 5.  We will use 5 to write to the child process; 0 will be the */
    /* child process' stdin.                                          */
    /******************************************************************/
    pipe(pipe2);    /* file descriptors 0 and 5 */
    write_to_adder = fdopen(pipe2[1], "w");
    fcntl(pipe2[1], F_SETFD, FD_CLOEXEC | fcntl(pipe2[1], F_GETFD));
 
    /******************************************************************/
    /* The file descriptors are now set as follows:                   */
    /*                                                                */
    /* 0 (pipe2[0])---child's stdin                                   */
    /* 1 (pipe1[1])---child's stdout                                  */
    /* 2 (stderr)                                                     */
    /* 3 (original_stdout)                                            */
    /* 4 (read_from_adder)                                            */
    /* 5 (write_to_adder)                                             */
    /*                                                                */
    /* Start the simple integer adder as a child process.  Note: the  */
    /* tpf_fork() function requires restricted macro permission.      */
    /******************************************************************/
    {
        struct tpf_fork_input tfi = {
            "bin/simple_integer_adder",
            TPF_FORK_FILE,
            TPF_FORK_IS_BALANCE
        };
        tpf_fork(&tfi);
    }
 
    /******************************************************************/
    /* Close the ends of the pipes that the child is using.           */
    /******************************************************************/
    close(pipe2[0]);
    close(pipe1[1]);
 
    /******************************************************************/
    /* Calculate the fibonacci series.                                */
    /******************************************************************/
    {
        int counter = SERIES_COUNT;
        int last = 1;
        int next = 1;
 
        fprintf(original_stdout, "%d", last);
 
        while (--counter)
        {
            fprintf(write_to_adder, "%d %d\n", last, next);
            fflush(write_to_adder);
            last = next;
            fprintf(original_stdout, " %d", last);
            fscanf(read_from_adder, "%d", &next);
        }
    }
    /******************************************************************/
    /* Close the working file streams.                                */
    /******************************************************************/
    fclose(original_stdout);
    fclose(write_to_adder);
    fclose(read_from_adder);
 
    return 0;
}

Related Information

See Appendix E, Programming Support for the TPF File System for more information about TPF File System C Functions.