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 shells) or named (see below) act like FIFOs (First In, First Out). We have already seen examples of how to use pipes in the shell, but let's take one more 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 shells, have names (i.e.: they are linked, whereas shell pipes are not). [22] The command to create a named pipe is mkfifo:
$ mkfifo a_pipe $ ls -il total 0 169 prw-rw-r-- 1 queen queen 0 Dec 10 14:12 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 Dec 10 15:37 a_pipe| 169 prw-rw-r-- 2 queen queen 0 Dec 10 15: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 C-z to suspend the process... # zsh: 3452 suspended ls -d /proc/[0-9] > a_pipe # # ...Then put in into the background: # $ bg [1] + continued ls -d /proc/[0-9] > a_pipe # # now read from the pipe... # $ head -5 <the_same_pipe # # ...the writing process terminates # [1] + 3452 done ls -d /proc/[0-9] > a_pipe /proc/1/ /proc/2/ /proc/3/ /proc/4/ /proc/5/ # |
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 # zsh: 741 suspended head -5 < a_pipe # # Put it into the background... # $ bg [1] + continued 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] + 741 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.
[22] Other differences exist between the two kinds of pipes, but they are beyond the scope of this book.