Previously, Streams were described as stacks of modules, with each module (except the head) connected to one upstream module and one downstream module. While this can be suitable for many applications, others need the ability to multiplex Streams in a variety of configurations. Typical examples are terminal window facilities, and internetworking protocols (that might route data over several subnetworks).
An example of a multiplexer is a module that multiplexes data from several upper Streams to a single lower Stream. An upper Stream is one that is upstream from the multiplexer, and a lower Stream is one that is downstream from the multiplexer. A terminal windowing facility might be implemented in this fashion, where each upper Stream is associated with a separate window.
A second type of multiplexer might route data from a single upper Stream to one of several lower Streams. An internetworking protocol could take this form, where each lower Stream links the protocol to a different physical network.
A third type of multiplexer might route data from one of many upper Streams to one of many lower Streams.
The STREAMS mechanism supports the multiplexing of Streams through special pseudo-device drivers. A user can activate a linking facility mechanism within the STREAMS framework to dynamically build, maintain, and dismantle multiplexed Stream configurations. Simple configurations like those shown in the three previous figures can be combined to form complex, multilevel multiplexed Stream configurations.
STREAMS multiplexing configurations are created in the kernel by interconnecting multiple Streams. Conceptually, a multiplexer can be divided into two components--the upper multiplexer and the lower multiplexer. The lower multiplexer acts as a Stream head for one or more lower Streams. The upper multiplexer acts as a device for one or more upper Streams. It is up to the implementation how data is passed between the upper and lower multiplexer. Chapter 13, Multiplexing covers implementing multiplexers.