Add Book to My BookshelfPurchase This Book Online

Chapter 13 - Interprocess Communication

UNIX Systems Programming for SVR4
David A. Curry
 Copyright © 1996 O'Reilly & Associates, Inc.

FIFOs
Pipes are extraordinarily useful, but suffer from one major limitation: they can only be used between related processes. To get around this limitation, the FIFO (first-in, first-out) was invented. FIFOs are often called named pipes, because they are associated with an entry in the filesystem. This name allows them to be used by processes that are not related to each other.
Just like pipes, FIFOs can have multiple processes writing to them. However, if this is the case, each writer must be careful to keep his writes no larger than PIPE_BUF bytes, or the data from multiple processes will become intermixed. In Solaris 2.x, FIFOs are full-duplex communications channels that allow bidirectional communication, but this behavior is not standard, and should not be relied upon if portability is an issue.
FIFOs can be created on most System V systems with the mknod function, which is used for creating special device files of all types. However, the POSIX standard specifies a function just for creating FIFOs, called mkfifo:
    #include <sys/types.h>
    #include <sys/stat.h>
    int mkfifo(const char *path, mode_t mode);
The path parameter provides a pathname to the FIFO to be created, which must not already exist. The mode argument contains a set of permission bits to set on the FIFO; these are modified by the process' umask value. Upon successful completion, mkfifo returns 0. If it fails, it returns -1 and sets errno to indicate the error.
You can also create a FIFO on most systems with the mkfifo command. This lets you create a FIFO using a shell command, and then access it using normal I/O redirection.
Once a FIFO has been created, it must be opened for use with the open function (see Chapter 3, Low-Level I/O Routines). When a FIFO is opened, the O_NONBLOCK option affects what happens:
 If O_NONBLOCK is not specified (the usual case), an open for reading only blocks until another process opens the FIFO for writing. Similarly, an open for writing only blocks until another process opens the FIFO for reading.
 If O_NONBLOCK is specified, an open for reading only returns immediately. But an open for writing only will return an error if no process has yet opened the FIFO for reading.
As with pipes, an attempt to write to a FIFO that has no process reading it will generate a SIGPIPE signal. When the last writer on a FIFO closes it, an end-of-file indication is generated for the reader.
Examples 13-4 and 13-5 show two programs, a server and a client, that use a FIFO to communicate. The server simply prints any data it receives from the client.
Example 13-4:  fifo-srvr
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define FIFONAME    "myfifo"
int
main(void)
{
    int n, fd;
    char buf[1024];
    /*
     * Remove any previous FIFO.
     */
    unlink(FIFONAME);
    /*
     * Create the FIFO.
     */
    if (mkfifo(FIFONAME, 0666) < 0) {
        perror("mkfifo");
        exit(1);
    }
    /*
     * Open the FIFO for reading.
     */
    if ((fd = open(FIFONAME, O_RDONLY)) < 0) {
        perror("open");
        exit(1);
    }
    /*
     * Read from the FIFO until end-of-file and
     * print what we get on the standard output.
     */
    while ((n = read(fd, buf, sizeof(buf))) > 0)
        write(1, buf, n);
    close(fd);
    exit(0);
}
Example 13-5:  fifo-clnt
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define FIFONAME    "myfifo"
int
main(void)
{
    int n, fd;
    char buf[1024];
    /*
     * Remove any previous FIFO.
     */
    unlink(FIFONAME);
    /*
     * Create the FIFO.
     */
    if (mkfifo(FIFONAME, 0666) < 0) {
        perror("mkfifo");
        exit(1);
    }
    /*
     * Open the FIFO for reading.
     */
    if ((fd = open(FIFONAME, O_RDONLY)) < 0) {
        perror("open");
        exit(1);
    }
    /*
     * Read from the FIFO until end-of-file and
     * print what we get on the standard output.
     */
    while ((n = read(fd, buf, sizeof(buf))) > 0)
        write(1, buf, n);
    close(fd);
    exit(0);
}
    % fifo-srvr &
    % fifo-clnt < /etc/motd
    Sun Microsystems Inc.   SunOS 5.3       Generic September 1993
The server process first uses unlink to delete any old FIFO, and then calls mkfifo to create a new one. This is not strictly necessary, but insures that the FIFO has the proper modes and ownership. The server then opens the FIFO for reading, and copies anything it receives to the standard output. The client opens the FIFO (which has been created by the server) for writing, and copies its standard input to the FIFO.

Previous SectionNext Section
Books24x7.com, Inc © 2000 –  Feedback