Monday, July 06, 2009

Linux FIFO



FIFO stands for "First in/First out", a part of interprocess communication mechanism. FIFO actually a named pipe (see manual page about pipe) used for communication between unrelated process. The kernel share it to be a part of file system, so multiple process can use (read/write) it concurrently. When data exchange occurs in a FIFO, the kernel passes all data internally without writing to the file system. Many real-time application use this method because it's unbuffered behavior, drastically reduce read/write process.

To create a FIFO, use mkfifo utility shipped by Linux's coreutils, in C way, we will need use mkfifo system call to create and then use it for read/write as like as working with a regular file.

Example to create FIFO:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int ret = mkfifo("/tmp/myfifo", 0666);
if (ret == -1)
    perror("mkfifo");


If the call success it should create a FIFO named "/tmp/myfifo", then sender or receiver process can open and exchange data via read and write. Normally reading or writing from a FIFO should blocking, but in Linux, opening a FIFO with read and write access always success both in blocking or unblocking mode.

Sender:
int fd;
unsigned char cmd = 0xff;
fd = open("/tmp/myfifo", O_RDWR | O_NONBLOCK, 0666);
if (fd == -1) {
    perror("open");
...
}
ret = write(cmd, &cmd, sizeof(cmd));
if (ret == -1) {
/* When write fails because the receiver has not opening the FIFO for reading, the kernel will send SIGPIPE (broken pipe) signal. */
    perror("write");
...
}


Receiver:
int fd;
unsigned char cmd;
fd = open("/tmp/myfifo", O_RDWR | O_NONBLOCK, 0666);
if (fd == -1) {
    perror("open");
...
}
ret = read(fd, &cmd, sizeof(cmd));
if (ret == -1) {
    perror("read");
...
}


Because this blocking behavior, application programmer should be very careful when write their codes to prevent deadlocks.

Reference:
Linux manual page: mkfifo, FIFO.