Pipes and FIFOs can be accessed through the operating system routines read(2), write(2), ioctl(2), close(2), putmsg(2), putpmsg(2), getmsg(2), getpmsg(2), and poll(2). For FIFOs, open(2) is also used.
read(2) or getmsg(2)) are used to read from a pipe or FIFO. Data can be read from either end of a pipe. On success, the read(2) returns the number of bytes read and buffered. When the end of the data is reached, read(2) returns 0.
When a user process attempts to read from an empty pipe (or FIFO), the following happens:
If one end of the pipe is closed, 0 is returned, indicating the end of the file.
If the write side of the FIFO has closed, read(2) returns 0 to indicate the end of the file.
If some process has the FIFO open for writing, or both ends of the pipe are open, and O_NDELAY is set, read(2) returns 0.
If some process has the FIFO open for writing, or both ends of the pipe are open, and O_NONBLOCK is set, read(2) returns -1 and sets errno to EAGAIN.
If O_NDELAY and O_NONBLOCK are not set, the read call blocks until data is written to the pipe, until one end of the pipe is closed, or the FIFO is no longer open for writing.
When a user process calls write(2), data is sent down the associated Stream. If the pipe or FIFO is empty (no modules pushed), data written is placed on the read queue of the other Stream for pipes, and on the read queue of the same Stream for FIFOs. Since the size of a pipe is the number of unread data bytes, the written data is reflected in the size of the other end of the pipe.
If a user process issues write(2) with 0 as the number of bytes to send a pipe or FIFO, 0 is returned, and, by default, no message is sent down the Stream. However, if a user must send a zero-length message downstream, SNDZERO ioctl(2) can be used to change this default behavior. If SNDZERO is set in the Stream head, write(2) requests of 0 bytes generate a zero-length message and sends the message down the Stream. If SNDZERO is not set, no message is generated and 0 is returned to the user.
The I_GWROPT ioctl(2) is used to get the current write settings.
If multiple processes simultaneously write to the same pipe, data from one process can be interleaved with data from another process, if modules are pushed on the pipe or the write is greater than PIPE_BUF. The order of data written is not necessarily the order of data read. To ensure that writes of less than PIPE_BUF bytes are not interleaved with data written by other processes, any modules pushed on the pipe should have a maximum packet size of at least PIPE_BUF.
PIPE_BUF is an implementation-specific constant that specifies the maximum number of bytes that are atomic when writing to a pipe. When writing to a pipe, write requests of PIPE_BUF or fewer bytes are not interleaved with data from other processes doing writes to the same pipe. However, write requests of more than PIPE_BUF bytes may have data interleaved on arbitrary byte boundaries with writes by other processes whether or not the O_NONBLOCK or O_NDELAY flag is set.
If the module packet size is at least the size of PIPE_BUF, the Stream-head packages the data in such a way that the first message is at least PIPE_BUF bytes. The remaining data may be packaged into smaller or equal-sized blocks depending on buffer availability. If the first module on the Stream cannot support a packet of PIPE_BUF, atomic writes on the pipe cannot be guaranteed.
close(2) closes a pipe or FIFO and dismantles its associated Streams. On the last close of one end of a pipe, an M_HANGUP message is sent to the other end of the pipe. Subsequent read(2) or getmsg(2) calls on that Stream head return the number of bytes read and zero when there are no more data. Subsequent write(2) or putmsg(2) requests fail with errno set to EPIPE. If the other end of the pipe is mounted, the last close of the pipe forces it to be unmounted.