Named Pipes
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 D V E R T I S E M E N T
What Is A Named Pipe?
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.
Creating A Named Pipe With The mknod Command
A named pipe may be created either via the 'mknod' (or its newer replacement,
'mkfifo'), or via the mknod() system call (or by the
POSIX-compliant 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
The 'p' on the first column denotes this is a named pipe. Just like any file in
the system, it has access permissions, that define which users may open the
named pipe, and whether for reading, writing or both.
Opening A Named Pipe For Reading Or Writing
Opening a named pipe is done just like opening any other file in the system,
using the open() system call, or using the fopen()
standard C function. If the call succeeds, we get a file descriptor (in the case
of 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 fopen().
Reading/Writing From/To A Named Pipe
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:
- Either Read Or Write - a named pipe cannot be opened for both
reading and writing. The process opening it must choose one mode, and stick
to it until it closes the pipe.
- Read/Write Are Blocking - when a process reads from a named pipe
that has no data in it, the reading process is blocked. It does not receive
an end of file (EOF) value, like when reading from a file. When a process
tries to write to a named pipe that has no reader (e.g. the reader process
has just closed the named pipe), the writing process gets blocked, until a
second process re-opens the named pipe.
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. This, however, is out of the scope
of our tutorial. For info about how to do that, and how to handle a non-blocking
pipe, please refer to the manual pages of 'open(2)', fcntl(2), read(2) and
write(2).
Named Pipe - A Complete Example
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.
As you can see, the contents of the '.plan' file has been printed out.
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
When you're done playing, stop the program, and don't forget to remove the named
pipe from the file system.
Few Words About Sockets
Various sockets-based mechanisms may be used to communicate amongst
processes. The underlying communications protocol may be TCP, UDP, IP, or any
other protocol from the TCP/IP protocols family. There is also a socket of type
'Unix-domain', which uses some protocol internal to the operating system to
communicate between processes all residing on a single machine. Unix-domain
sockets are similar to named pipes in that the communicating processes use a
file in the system to connect to establish a connection.
|