Let's get back to the
example of pipes, as it is quite interesting and is also a good
illustration of the links notion. When you use a pipe in a command
line, the shell
creates the pipe for you and operates so
that the command before the pipe writes to it, while the command
after the pipe reads from it. All pipes, whether they be anonymous
(like the ones used
by the shell
s) or named
(see below) act like FIFOs (First In, First Out). We've already
seen examples of how to use pipes in the shell
, but let's
take another look for the sake of our demonstration:
$ ls -d /proc/[0-9] | head -5 /proc/1/ /proc/2/ /proc/3/ /proc/4/ /proc/5/
One thing that you will not notice in this
example (because it happens too fast for one to see) is that writes on
pipes are blocking. This means that when the ls command
writes to the pipe, it is blocked until a process at the other end reads
from the pipe. In order to visualize the effect, you can create named
pipes, which unlike the pipes used by shell
s, have names (i.e.:
they are linked, whereas shell
pipes are not)[5]. The command to create a named pipe is
mkfifo:
$ mkfifo a_pipe $ ls -il total 0 169 prw-rw-r-- 1 queen queen 0 Aug 6 19:37 a_pipe| # # You can see that the link counter is 1, and that the output shows # that the file is a pipe ('p'). # # You can also use ln here: # $ ln a_pipe the_same_pipe $ ls -il total 0 169 prw-rw-r-- 2 queen queen 0 Aug 6 19:37 a_pipe| 169 prw-rw-r-- 2 queen queen 0 Aug 6 19:37 the_same_pipe| $ ls -d /proc/[0-9] >a_pipe # # The process is blocked, as there is no reader at the other end. # Type Control Z to suspend the process... # [1]+ Stopped ls -F --show-control-chars --color=auto -d /proc/[0-9] >a_pipe # # ...Then put in into the background: # $ bg [1]+ ls -F --show-control-chars --color=auto -d /proc/[0-9] >a_pipe & # # now read from the pipe... # $ head -5 <the_same_pipe # # ...the writing process terminates # /proc/1/ /proc/2/ /proc/3/ /proc/4/ /proc/5/ [1]+ Done ls -F --show-control-chars --color=auto -d /proc/[0-9] >a_pipe $
Similarly, reads are also blocking. If we execute the above commands in the reverse order, we will see that head blocks, waiting for some process to give it something to read:
$ head -5 <a_pipe # # Program blocks, suspend it: C-z # [1]+ Stopped head -5 <a_pipe # # Put it into the background... # $ bg [1]+ head -5 <a_pipe & # # ...And give it some food :) # $ ls -d /proc/[0-9] >the_same_pipe /proc/1/ /proc/2/ /proc/3/ /proc/4/ /proc/5/ [1]+ Done head -5 <a_pipe $
You can also see an undesired effect in the previous example: the ls command has terminated before the head command took over. The consequence is that you were immediately returned to the prompt, but head executed later and you only saw its output after returning.
[5] Other differences exist between the two kinds of pipes, but they are beyond the scope of this book.