STREAMS Programming Guide

Persistent Links

Keeping a process running merely to hold the multiplexer configuration together is not always desirable, so, “free standing” links below a multiplexer are needed. A persistent link is such a link. It is similar to a STREAMS multiplexer link except that a process is not needed to hold the links together. After the multiplexer has been set up, the process may close all file descriptors and exit, and the multiplexer remains intact.

With I_LINK and I_UNLINK ioctl(2) the file descriptor associated with the stream above the multiplexer used to set up the lower multiplexer connections must remain open for the duration of the configuration. Closing the file descriptor associated with the controlling stream dismantles the whole multiplexing configuration.

Two ioctl(2)s, I_PLINK and I_PUNLINK, are used to create and remove persistent links that are associated with the stream above the multiplexer. close(2) and I_UNLINK are not able to disconnect the persistent links (see strconf(1) and strchg(1)).

The format of I_PLINK is:


ioctl(fd0, I_PLINK, fd1)

The first file descriptor, fd0, must reference the stream connected to the multiplexing driver and the second file descriptor, fd1, must reference the stream to be connected below the multiplexer. The persistent link can be created as follows:


upper_stream_fd = open("/dev/mux", O_RDWR);
lower_stream_fd = open("/dev/driver", O_RDWR);
muxid = ioctl(upper_stream_fd, I_PLINK, lower_stream_fd);
/*
 * save muxid in a file
 */
exit(0);

The persistent link can still exist even if the file descriptor associated with the upper stream to the multiplexing driver is closed. The I_PLINK ioctl(2) returns an integer value, muxid, that can be used for dismantling the multiplexing configuration. If the process that created the persistent link still exists, it may pass the muxid value to some other process to dismantle the link, if the dismantling is desired, or it can leave the muxid value in a file so that other processes may find it later.

Several users can open the MUX driver and send data to Driver1 since the persistent link to Driver1 remains intact.

The I_PUNLINK ioctl(2) is used to dismantle the persistent link. Its format is:


ioctl(fd0, I_PUNLINK, muxid)

where fd0 is the file descriptor associated with stream connected to the multiplexing driver from above. The muxid is returned by the I_PLINK ioctl(2) for the stream that was connected below the multiplexer. I_PUNLINK removes the persistent link between the multiplexer referenced by fd0 and the stream to the driver designated by the muxid. Each of the bottom persistent links can be disconnected individually. An I_PUNLINK ioctl(2) with the muxid value of MUXID_ALL will remove all persistent links below the multiplexing driver referenced by fd0.

The following code example shows how to dismantle the previously given configuration:


fd = open("/dev/mux", O_RDWR);
/*
 * retrieve muxid from the file
 */
ioctl(fd, I_PUNLINK, muxid);
exit(0);

Do not use the I_PLINK and I_PUNLINK ioctls with I_LINK and I_UNLINK. Any attempt to unlink a regular link with I_PUNLINK or to unlink a persistent link with the I_UNLINK ioctl(2) causes the errno value of EINVAL to be returned.

Because multilevel multiplexing configurations are allowed in STREAMS, persistent links could exist below a multiplexer whose stream is connected to the above multiplexer by regular links. Closing the file descriptor associated with the controlling stream will remove the regular link but not the persistent links below it. On the other hand, regular links are allowed to exist below a multiplexer whose stream is connected to the above multiplexer with persistent links. In this case, the regular links will be removed if the persistent link above is removed and no other references to the lower streams exist.

The construction of cycles is not allowed when creating links. A cycle could be constructed by:

  1. Creating a persistent link of multiplexer 2 below multiplexer 1

  2. Closing the controlling file descriptor associated with the multiplexer 2

  3. Reopening the file descriptor again

  4. Linking the multiplexer 1 below the multiplexer 2

This is not allowed. The operating system prevents a multiplexer configuration from containing a cycle to ensure that messages cannot be routed infinitely, which would create an infinite loop or overflow the kernel stack.