STREAMS-based pipes and FIFOs can be accessed through the operating system routines read(2), write(2), ioctl(2), close(2), putmsg(2), getmsg(2), and poll(2). If FIFOs, open is also used.
The read (or getmsg) system call is used to read from a pipe or FIFO. A user reads data from a Stream (not from a data buffer as was done prior to Release 4). Data can be read from either end of a pipe.
On success, the read returns the number of bytes read and placed in the buffer. When the end of the data is reached, the read returns 0.
When a user process attempts to read from an empty pipe (or FIFO), the following will happen:
When a user process calls the write system call, 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 STREAMS-based pipes, and on the read queue of the same Stream for FIFOs. Because 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 with 0 as the number of bytes to send down a STREAMS-based pipe or FIFO, 0 is returned, and by default no message is sent down the Stream. However, if a user requires that a 0-length message be sent downstream, an ioctl call may be used to change this default behavior. The flag SNDZERO supports this. If SNDZERO is set in the Stream head, write requests of 0 bytes generate a 0-length message and send the message down the Stream. If SNDZERO is not set, no message is generated and 0 is returned to the user.
To toggle the SNDZERO bit, the ioctl I_SWROPT is used. If arg in the ioctl call is set to SNDZERO and the SNDZERO bit is off, the bit is turned on. If arg is set to 0 and the SNDZERO bit is on, the bit is turned off.
The ioctl I_GWROPT is used to return 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 sequence of data written is not necessarily the sequence of data read. To ensure that writes of less than PIPE_BUF bytes are not be interleaved with data written from other processes, any modules pushed on the pipe should have a maximum packet size of at least PIPE_BUF.
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 larger 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.
The close system call 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 upstream to the other end of the pipe. Later read or getmsg calls on that Stream head return the number of bytes read and 0 when there is no more data. Later write or putmsg requests will fail with errno set to EIO. If the pipe has been mounted using fattach, the pipe must be unmounted before calling close; otherwise, the Stream will not be dismantled. If the other end of the pipe is mounted, the last close of the pipe will force it to be unmounted.