File and device input/output

Basic STREAMS operations

This section describes the basic set of operations for manipulating STREAMS entities.

A STREAMS driver is similar to a traditional character I/O driver in that it has one or more nodes associated with it in the file system, and it is accessed using the open system call. Typically, each file system node corresponds to a separate minor device for that driver. Opening different minor devices of a driver causes separate Streams to be connected between a user process and the driver. The file descriptor returned by the open call is used for further access to the Stream. If the same minor device is opened more than once, only one Stream is created; the first open call creates the Stream, and subsequent open calls return a file descriptor that references that Stream. Each process that opens the same minor device shares the same Stream to the device driver.

Once a device is opened, a user process can send data to the device using the write system call and receive data from the device using the read system call. Access to STREAMS drivers using read and write is compatible with the traditional character I/O mechanism.

The close system call closes a device and dismantles the associated Stream when the last open reference to the Stream is given up.

The following example shows how a simple Stream is used. In the example, the user program interacts with a communications device that provides point-to-point data transfer between two computers. Data written to the device transmitted over the communications line, and data arriving on the line can be retrieved by reading from the device.

   #include <fcntl.h>

main() { char buf[1024]; int fd, count;

if ((fd = open("/dev/comm/01", O_RDWR)) < 0) { perror("open failed"); exit(1); }

while ((count = read(fd, buf, 1024)) > 0) { if (write(fd, buf, count) != count) { perror("write failed"); break; } } exit(0); }

In the example, /dev/comm/01 identifies a minor device of the communications device driver. When this file is opened, the system recognizes the device as a STREAMS device and connects a Stream to the driver. ``Stream to communication driver'' shows the state of the Stream following the call to open.

Stream to communication driver

This example illustrates a user reading data from the communications device and then writing the input back out to the same device. In short, this program echoes all input back over the communications line. The example assumes that a user sends data from the other side of the communications line. The program reads up to 1024 bytes at a time, and then writes the number of bytes just read.

The read call returns the available data, which may contain fewer than 1024 bytes. If no data is currently available at the Stream head, the read call blocks until data arrive.

Similarly, the write call attempts to send count bytes to /dev/comm/01. However, STREAMS implements a flow control mechanism that prevents a user from exhausting system resources by flooding a device driver with data.

Flow control controls the rate of message transfer among the modules, drivers, Stream head, and processes. Flow control is local to each Stream and advisory (voluntary). It limits the number of characters that can be queued for processing at any queue in a Stream, and limits buffers and related processing at any queue and in any one Stream, but does not consider buffer pool levels or buffer usage in other Streams. Flow control is not applied to high-priority messages.

If the Stream exerts flow control on the user, the write call blocks until flow control is relieved. The call does not return until it has sent count bytes to the device. exit, which is called to terminate the user process, also closes all open files, and thereby dismantling the Stream in this example.

Next topic: Benefits of STREAMS
Previous topic: Record locking and future releases of the UNIX system

© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 27 April 2004