6.3 FIFOs

Team-FLY

Pipes are temporary in the sense that they disappear when no process has them open . POSIX represents FIFOs or named pipes by special files that persist even after all processes have closed them. A FIFO has a name and permissions just like an ordinary file and appears in the directory listing given by ls . Any process with the appropriate permissions can access a FIFO. Create a FIFO by executing the mkfifo command from a shell or by calling the mkfifo function from a program.

The mkfifo function creates a new FIFO special file corresponding to the pathname specified by path . The mode argument specifies the permissions for the newly created FIFO.

  SYNOPSIS  #include <sys/stat.h>    int mkfifo(const char *path, mode_t mode);  POSIX  

If successful, mkfifo returns 0. If unsuccessful , mkfifo returns “1 and sets errno . A return value of “1 means that the FIFO was not created. The following table lists the mandatory errors for mkfifo .

errno

cause

EACCES

search permission on a component of path prefix denied, or write permission on parent directory of FIFO denied

EEXIST

named file already exists

ELOOP

a loop exists in resolution of path

ENAMETOOLONG

length of path exceeds PATH_MAX , or a pathname component is longer than NAME_MAX

ENOENT

component of path prefix specified by path does not name existing file, or path is an empty string

ENOSPC

directory to contain new file cannot be extended, or the file system is out of resources

ENOTDIR

component of path prefix is not a directory

EROFS

the named file would reside on a read-only file system

Unlike many other I/O functions, mkfifo does not set errno to EINTR .

Example 6.8

The following code segment creates a FIFO, myfifo , in the current working directory. This FIFO can be read by everybody but is writable only by the owner.

 #define FIFO_PERMS  (S_IRUSR  S_IWUSR  S_IRGRP  S_IROTH) if (mkfifo("myfifo", FIFO_PERMS) == -1)    perror("Failed to create myfifo"); 

Remove a FIFO the same way you remove a file. Either execute the rm command from a shell or call unlink from a program. Example 6.9 shows a code segment that removes the FIFO that Example 6.8 created. The code assumes that the current working directory of the calling program contains myfifo .

Example 6.9

The following code segment removes myfifo from the current working directory.

 if (unlink("myfifo") == -1)    perror("Failed to remove myfifo"); 

Program 6.4 creates a named pipe from a path specified on the command line. It then forks a child. The child process writes to the named pipe, and the parent reads what the child has written. Program 6.4 includes error checking, identifying each message with the process ID. This identification of messages is important because the parent and child share standard error.

Program 6.4 parentchildfifo.c

The parent reads what its child has written to a named pipe .

 #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/stat.h> #include <sys/wait.h> #define BUFSIZE 256 #define FIFO_PERM  (S_IRUSR  S_IWUSR) int dofifochild(const char *fifoname, const char *idstring); int dofifoparent(const char *fifoname); int main (int argc, char *argv[]) {    pid_t childpid;    if (argc != 2) {                           /* command line has pipe name */       fprintf(stderr, "Usage: %s pipename\n", argv[0]);       return 1;    }    if (mkfifo(argv[1], FIFO_PERM) == -1) {           /* create a named pipe */       if (errno != EEXIST) {          fprintf(stderr, "[%ld]:failed to create named pipe %s: %s\n",               (long)getpid(), argv[1], strerror(errno));          return 1;       }    }    if ((childpid = fork()) == -1){       perror("Failed to fork");       return 1;    }    if (childpid == 0)                                   /* The child writes */       return dofifochild(argv[1], "this was written by the child");    else       return dofifoparent(argv[1]); } 

The dofifochild function of Program 6.5 shows the actions taken by the child to write to the pipe. Notice that Program 6.5 uses snprintf rather than sprintf to construct the message. The first three parameters to snprintf are the buffer address, the buffer size and the format string. The snprintf does not write beyond the specified size and always inserts a null character to terminate what it has inserted. Program 6.5 also uses r_write instead of write to make sure that the child writes the entire message.

Program 6.5 dofifochild.c

The child writes to the pipe and returns .

 #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/stat.h> #include "restart.h" #define BUFSIZE 256 int dofifochild(const char *fifoname, const char *idstring) {    char buf[BUFSIZE];    int fd;    int rval;    ssize_t strsize;    fprintf(stderr, "[%ld]:(child) about to open FIFO %s...\n",           (long)getpid(), fifoname);    while (((fd = open(fifoname, O_WRONLY)) == -1) && (errno == EINTR)) ;    if (fd == -1) {       fprintf(stderr, "[%ld]:failed to open named pipe %s for write: %s\n",              (long)getpid(), fifoname, strerror(errno));       return 1;    }    rval = snprintf(buf, BUFSIZE, "[%ld]:%s\n", (long)getpid(), idstring);    if (rval < 0) {       fprintf(stderr, "[%ld]:failed to make the string:\n", (long)getpid());       return 1;    }    strsize = strlen(buf) + 1;    fprintf(stderr, "[%ld]:about to write...\n", (long)getpid());    rval = r_write(fd, buf, strsize);    if (rval != strsize) {       fprintf(stderr, "[%ld]:failed to write to pipe: %s\n",              (long)getpid(), strerror(errno));       return 1;    }    fprintf(stderr, "[%ld]:finishing...\n", (long)getpid());    return 0; } 

The dofifoparent function of Program 6.6 shows the actions taken by the parent to read from the pipe.

Exercise 6.10

What happens to the named pipe after the processes of Program 6.4 exit?

Answer:

Since neither process called unlink for the FIFO, it still exists and appears in the directory listing of its path.

Program 6.6 dofifoparent.c

The parent reads what was written to a named pipe .

 #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/stat.h> #include "restart.h" #define BUFSIZE 256 #define FIFO_MODES O_RDONLY int dofifoparent(const char *fifoname) {    char buf[BUFSIZE];    int fd;    int rval;    fprintf(stderr, "[%ld]:(parent) about to open FIFO %s...\n",                        (long)getpid(), fifoname);    while (((fd = open(fifoname, FIFO_MODES)) == -1) && (errno == EINTR))  ;    if (fd == -1) {       fprintf(stderr, "[%ld]:failed to open named pipe %s for read: %s\n",              (long)getpid(), fifoname, strerror(errno));       return 1;    }    fprintf(stderr, "[%ld]:about to read...\n", (long)getpid());    rval = r_read(fd, buf, BUFSIZE);    if (rval == -1) {       fprintf(stderr, "[%ld]:failed to read from pipe: %s\n",              (long)getpid(), strerror(errno));       return 1;    }    fprintf(stderr, "[%ld]:read %.*s\n", (long)getpid(), rval, buf);    return 0; } 
Team-FLY


Unix Systems Programming
UNIX Systems Programming: Communication, Concurrency and Threads
ISBN: 0130424110
EAN: 2147483647
Year: 2003
Pages: 274

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net