control buffers messages and does not accept messages without sufficient buffer space.
This process involves exchanges of control messages between queues in adjacent modules.
A user process writes data to a device using either the write() or putmsg() system call.
The write() system call writes raw data to the stream, whereas putmsg() allows the user process to specify a message.
Regardless of the system call used by the user process, the stream head copies the data into a message and delivers it to the queue for the next module in line.
This copying of messages continues until the message is copied to the driver end and hence the device.
Similarly, the user process reads data from the stream head using either the read() or getmsg() system call.
If read() is used, the stream head gets a message from its adjacent queue and returns ordinary data (an unstructured byte stream) to the process.
If getmsg() is used, a message is returned to the process.
STREAMS I/O is asynchronous (or nonblocking) except when the user process communicates with the stream head.
When writing to the stream, the user process will block, assuming the next queue uses flow control, until there is room to copy the message.
Likewise, the user process will block when reading from the stream until data are available.
As mentioned, the driver end—like the stream head and modules—has a read and write queue.
However, the driver end must respond to interrupts, such as one triggered when a frame is ready to be read from a network.
Unlike the stream head, which may block if it is unable to copy a message to the next queue in line, the driver end must handle all incoming data.
Drivers must support flow control as well. However, if a device’s buffer is full, the