A taxonomy of I/O architectures



A bytepipe is a pipe which transports a logical sequence of bytes which is potentially neverending.

A bytepipe can be bidirectional or unidirectional. Examples of bidirectional bytepipes include UARTs and TCP connections.


A framepipe is a pipe which transports a logical sequence of frames. A frame is a sequence of zero or more bytes.

Generally, a framepipe

  • may or may not impose minimum length limitations,
  • may or may not impose maximum length limitations, and
  • may or may not require, or strongly expect, use of a specific header format within each frame.

A framepipe which does not require a specific header format and can transport arbitrary frames as a completely neutral carrier is called a neutral framepipe; a framepipe which requires a specific header format is called an application-specific or non-neutral framepipe.

A framepipe can be bidirectional or unidirectional. Examples of bidirectional framepipes include Ethernet ports (which are non-neutral as they require use of an Ethernet header) and SCTP connections (which are neutral). Example of unidirectional framepipes include USB bulk, interrupt and isochronous endpoints.

A neutral framepipe can be trivially adapted to function as a bytepipe by simply ignoring frame boundaries and treating the bytepipe as the concatenation of the contents of all the frames.

A bidirectional bytepipe or framepipe can be constructed from two unidirectional bytepipes/framepipes in opposite directions (for example, two USB endpoints). Alternately, all bidirectional bytepipes/framepipes can be viewed as the composition of two unidirectional bytepipes/framepipes.


A commandpipe is a pipe which accepts commands and, for each command, returns the result of the execution of that command.

A commandpipe will often allow multiple commands to be submitted for asynchronous and concurrent execution, or allow previously submitted commands to be aborted via further commands. Unlike framepipes, commandpipes frequently introduce the logically separate transport of commands and associated data. Moreover, whereas most framepipes will impose some kind of frame length limitation, common commandpipes are often designed to accept unbounded amounts of data associated with commands, and use separate transport mechanisms for transport of commands and data so as to allow data to be transferred efficiently.

Examples of commandpipes include SCSI, ATA, NVMe, and USB control endpoints.


An addresspipe is a pipe which accepts load/store operations and returns the results of those operations; as such, it is a kind of commandpipe, but one which is worth enumerating in its own right.

Logically, an addresspipe accepts a sequence of operations such as

  Load (address)        → value | Error
  Store(address, value) → OK    | Error

where address and value are unsigned integers of some given width. Usually values of multiple different widths will be supported and the load/store operations will be specialised in multiple instances for each of these widths. Other operations may also be supported, for example to support atomic operations.

Examples of addresspipes include Firewire. Although Firewire was largely replaced with USB, it should be noted that USB is based on framepipes and commandpipes, whereas Firewire was based on addresspipes, with Firewire devices being accessed in terms of register addresses.

The ultimate example of an addresspipe however is a CPU's own load/store instructions. In this regard, every memory operation ever issued by the code running on a CPU can be considered access to an addresspipe. Thus, it is common for access to other pipe types to be built on top of an addresspipe interface, as in MMIO.

An addresspipe is directional in that operations are issued by a master and handled by a slave. A device is a slave if it can receive operations, and a device is a master if it can initiate operations and receive their results. Some devices might be both masters and slaves; if there is, or can be, more than one master attached to an addresspipe, it is a multi-master addresspipe. Firewire devices, and other devices which can support DMA (or "bus mastering") are an example of this.

Even addresspipes which are multi-master will usually still be regarded as directional for some purposes. For example, PCIe supports DMA and is multi-master, but the topology is built around a tree rooted in the host (the “root complex”); thus the host has special status and there cannot (in conventional PCIe) be multiple root complexes. Some addresspipes are truly peer-to-peer with no special role for a host; for example, Firewire. As an aside, it is interesting to note that the formal title of the Firewire standard, IEEE 1394, is “Serial Bus”. What is significant here to note that the “Bus” in this term appears to be meant in the sense of a CPU's bus (i.e., an addresspipe), not in the electrical sense, which explains why the authors found this title meaningful, as the notion of a serial CPU bus is, or was at the time, a much more unusual proposition than serial communication in general. Of course, the notion of a serial bus has subsequently become normal and is the basis of modern technologies such as PCIe.

Note that the ordering of requests, or their responses sent to an addresspipe is not necessarily strongly defined; in the case of a CPU's memory addresspipe for example, this is subject to the memory model of the CPU's ISA, which might provide a strong or a weak memory model with few ordering guarantees.


A multipipe is a formation of multiple logical pipes and can be considered as a composition of one or more of the other kinds of pipe described above. Of note is the fact that these pipes do not all need to be of the the same type; for example, a USB device can be considered a multipipe including one commandpipe and zero or more framepipes. Another example of a multipipe is an SCTP connection, because SCTP can support multiple separate streams within one connection, making it a multi-framepipe.


A pipe implies (at least) two ends. To distinguish between a pipe and its ends, the term port is introduced. A port refers to an end of a pipe. In a TCP connection, for example, there is one pipe with two ports, existing on different hosts. If a bytepipe or framepipe is unidirectional, this implies that one of its ports will be transmit-only, and the other will be receive-only.

Consider the following universal representation of computer networking:

               (n+1)                            (n+1)
            -----------                      -----------
                 |                                |
                 v                                v
            -----------                      -----------
            |   (n)   |<====================>|   (n)   |
            -----------         [1]          -----------
                 |                                |
                 v                                v
            -----------                      -----------
               (n-1)                            (n-1)
Computer networking

A protocol machine (denoted (n) above) at a given layer n accepts service requests directed to its service interface from a higher-level protocol machine (n+1) or application client, translates it into a protocol data unit and transmits it by making service requests to the protocol machine (n-1) below it in turn. By virtue of this and corresponding activity in reverse at the peer, an association [1] is formed despite lack of any direct connection and communication is enabled.

To map the terminology introduced above to this model, the pipe is the association [1] and the ports are the entities (n) forming the endpoints of that association. The above shows a bidirectional point-to-point pipe which necessarily therefore has two ports.

The ports are accessed and made use of by means of the service interfaces they expose to a higher-layer entity. Note that the term port refers to the entity accessed by the service interface, not the service interface per se; the service interface for a port may be referred to as the port interface.

Pipes redux

If a pipe has two ports attached to it, it is point-to-point. If it has more than two ports attached to it, it is a multipoint pipe. This is referred to as the pipe order (akin to the graph theory use of the term).

... ----------- | | (n) |<=========>| ----------- | | ----------- | | (n) |<=========>| ----------- | | ----------- | | (n) |<=========>| ----------- | ...
A multipoint pipe

An example of a multipoint framepipe is a UDP pipe which is used to communicate with multiple other hosts using sendto(). The host can address multiple other entities attached to the “pipe” (in this case, the number of ports attached to the pipe is potentially equal to the number of hosts connected to the internet).

A multipoint pipe may seem like a mere special case of a commandpipe or addresspipe since any multipoint transmission can be seen as a combination of some data and some addressing information to identify the desired destination port attached to the multipipe; this (address, data) combination could be viewed as a command. However, this is mistaken because a multipoint pipe does not necessarily implement command semantics nor requires that what is transmitted over it constitute a command. To put it simply, we classify a pipe as a bytepipe, framepipe, commandpipe, etc. based on the nature of the payloads it delivers to any given port attached to that pipe, and the semantics of those payloads. If we were to consider something a commandpipe because making use of a port requires addressing it with some kind of command (for example, a POSIX write call), then there would be no pipes which are not considered commandpipes.

A multipoint pipe can be considered as a transformation of some given existing pipe type. For an existing non-multipoint pipe, this pipe is considered to transport objects (for bytepipes, bytes; for framepipes, frames; for commandpipes, command/response pairs):

object... ← pipe ← object...

The multipoint transmutation thus becomes:

(sourcePort, object)... ← multipoint(pipe) ← (destinationPort, object)...

In other words, service requests are made to a port passing a destination port identifier and an object of the kind accepted by the type of pipe in question, but received at another port as a source port identifier and that object. This also again illustrates why multipipes are not a variety of commandpipe; the port identifier cannot be taken to be a “command” because it is different on each end and reflects information effectively provided by the pipe itself, rather than information transported across it.

For an example, consider Ethernet. At its most fundamental, (full-duplex) Ethernet is a non-neutral point-to-point framepipe; however, in practice, Ethernet is used with switching devices to create what is, viewed within our model, a multipoint pipe. The “ports” of this device (other devices within the same broadcast domain) are addressed with MAC addresses.

We already introduced the concept of multipipes above, which allow two unidirectional point-to-point pipes to be composed to be considered one bidirectional point-to-point pipes, or a set of related pipes to be grouped together as in the case of USB. In fact, our notion of a multipoint pipe can trivially be reduced to the multipipe concept; a multipoint pipe is effectively just a set of pipes; that is, a multipipe. This set might be very large; it might, for example, be defined as “all hosts connected to the internet”. Rather than viewing the port identifier as metadata attached to a service request made to a port by a higher-level application, the port identifier can be viewed as identifying the specific pipe to use within a conceptual multipipe. Of course, at the lower layers, the physical realisation of this multipoint pipe/multipipe may well be built upon a single pipe, just as multiple TCP connections coexist on a single internet connection.

In general, we will refer to multipipes as multipoint pipes if the different point-to-point pipes within the multipipe have their opposite ports connected to different entities and the number of such pipes within the multipipe are liable to vary dynamically. Other usages of multipipes, such as use simply to group together a small number of related pipes as in USB, or to avoid multiple independent streams directed at the same entity as in the case of SCTP connections, will simply be referred to as multipipes, even though we likely could model them as multipoint pipes if we chose to.