One limitation of anonymous pipes is that only processes 'related' to the process that created the pipe (i.e. siblings of that process.) may communicate using them. If we want two un-related processes to communicate via pipes, we need to use named pipes.
A named pipe (also called a named FIFO, or just FIFO) is a pipe whose access point is a file kept on the file system. By opening this file for reading, a process gets access to the reading end of the pipe. By opening the file for writing, the process gets access to the writing end of the pipe. If a process opens the file for reading, it is blocked until another process opens the file for writing. The same goes the other way around.
A named pipe may be created either via the 'mknod' (or its newer replacement,
'mkfifo'), or via the
mknod() system call (or by the
mkfifo() function). To create a named pipe
with the file named 'prog_pipe', we can use the following command:
mknod prog_pipe p
We could also provide a full path to where we want the named pipe created. If we then type 'ls -l prog_pipe', we will see something like this:
prw-rw-r-- 1 choo choo 0 Nov 7 01:59 prog_pipe
Opening a named pipe is done just like opening any other file in the system,
open() system call, or using the
standard C function. If the call succeeds, we get a file descriptor (in the
open(), or a 'FILE' pointer (in the case of
fopen()), which we may use either for reading or for writing,
depending on the parameters passed to
open() or to
Reading from a named pipe is very similar to reading from a file, and the same goes for writing to a named pipe. Yet there are several differences:
Thus, when writing a program that uses a named pipe, we must take these limitations into account. We could also turn the file descriptor via which we access the named pipe to a non-blocking mode.
As an example to an obscure usage of named pipes, we will borrow some idea
from a program that allows one to count how many times they have been
"fingered" lately. As you might know, on many Unix systems, there is a finger
daemon, that accepts requests from users running the "finger" program, with
a possible user name, and tells them when this user last logged on, as well
as some other information. Amongst other thing, the finger daemon also checks
if the user has a file named '.plan' (that is dot followed by "plan") in her
home directory. If there is such a file, the finger daemon opens it, and
prints its contents to the client. For example, on my Linux machine,
fingering my account might show something like:
[choo@simey1 ~]$ finger choo Login: choo Name: guy keren Directory: /home/choo Shell: /bin/tcsh On since Fri Nov 6 15:46 (IDT) on tty6 No mail. Plan: - Breed a new type of dogs. - Water the plants during all seasons. - Finish the next tutorial on time.
This feature of the finger daemon may be used to create a program that
tells the client how many times i was fingered. For that to work, we first
create a named pipe, where the '.plan' file resides:
mknod /home/choo/.plan p
If i now try to finger myself, the output will stop before showing the 'plan' file. How so? this is because of the blocking nature of a named pipe. When the finger daemon opens my '.plan' file, there is no write process, and thus the finger daemon blocks. Thus, don't run this on a system where you expect other users to finger you often.
The second part of the trick, is compiling the
named-pipe-plan.c program, and running it.
note that it contains the full path to the '.plan' file, so change that to
the appropriate value for your account, before compiling it. When you run
the program, it gets into an endless loop of opening the named pipe in
writing mode, write a message to the named pipe, close it, and sleep for
a second. Look at the program's source code for more information. A sample
of its output looks like this:
[choo@simey1 ~]$ finger choo Login: choo Name: guy keren Directory: /home/choo Shell: /bin/tcsh On since Fri Nov 6 15:46 (IDT) on tty6 No mail. Plan: I have been fingered 8 times today