8.2.2 Pipe States
A pipe has a limited number of states associated with it from the time of its creation to its termination. Each state corresponds to the data transfer state between the reader and the writer of the pipe, as illustrated in Figure 8.4.

Figure 8.4: States of a pipe.
8.2.3 Named and Unnamed Pipes
A kernel typically supports two kinds of pipe objects: named pipes and unnamed pipes. A
8.2.4 Typical Pipe Operations
The following set of operations can be performed on a pipe:
· create and destroy a pipe,
· read from or write to a pipe,
· issue control commands on the pipe, and
· select on a pipe.
Create and destroy operations are available, as shown in Table 8.1.
Table 8.1: Create and destroy operations.
Operation | Description |
---|---|
Pipe | Creates a pipe |
Open | Opens a pipe |
Close | Deletes or closes a pipe |
The pipe operation creates an unnamed pipe. This operation returns two descriptors to the calling task, and subsequent calls reference these descriptors. One descriptor is used only for writing, and the other descriptor is used only for reading.
Creating a named pipe is similar to creating a file; the specific call is implementation-dependent. Some common names for such a call are mknod and mkfifo. Because a named pipe has a recognizable name in the file system after it is created, the pipe can be opened using the open operation. The calling task must specify whether it is opening the pipe for the read operation or for the write operation; it cannot be both.
The close operation is the counterpart of the open operation. Similar to open, the close operation can only be performed on a named pipe. Some implementations will delete the named pipe permanently once the close operation completes.
Read and write operations are available, as shown in Table 8.2.
Table 8.2: Read and write operations.
Operation | Description |
---|---|
Read | Reads from the pipe |
Write | Writes to a pipe |
The read operation returns data from the pipe to the calling task. The task specifies how much data to read. The task may choose to block waiting for the remaining data to arrive if the size specified exceeds what is available in the pipe. Remember that a read operation on a pipe is a destructive operation because data is removed from a pipe during this operation, making it unavailable to other readers. Therefore, unlike a message queue, a pipe cannot be used for broadcasting data to multiple reader tasks.
A task, however, can consume a block of data originating from multiple writers during one read operation.
The write operation appends new data to the existing byte stream in the pipe. The calling task specifies the amount of data to write into the pipe. The task may choose to block waiting for additional buffer space to become free when the amount to write exceeds the available space.
No message boundaries exist in a pipe because the data maintained in it is unstructured. This issue represents the main structural difference between a pipe and a message queue. Because there are no message headers, it is impossible to determine the original producer of the data bytes. As mentioned earlier, another important difference between message queues and pipes is that data written to a pipe cannot be prioritized. Because each byte of data in a pipe has the same priority, a pipe should not be used when urgent data must be exchanged between tasks.
Control operations are available, as shown in Table 8.3.
Table 8.3: Control operations.