STREAMS Programming Guide

open Routine

The open(9E) routine of a device is called once for the initial open of the device, then is called again on subsequent reopens of the stream. Module open routines are called once for the initial push onto the stream and again on subsequent reopens of the stream.

Figure 7–8 Order of a Module's open Procedure

Diagram shows a stream consisting of three modules. This example
is used to describe the order in which the modules call the open routine.

The stream is analogous to a stack. Initially the driver is opened and as modules are pushed onto the stream, their open routines are invoked. Once the stream is built, this order reverses if a reopen of the stream occurs. For example, while building the stream shown in Figure 7–8, device A's open routine is called, followed by B's and C's when they are pushed onto the stream. If the stream is reopened, Module C's open routine is called first, followed by B's, and finally by A's.

Usually the module or driver does not check this, but the issue is raised so that dependencies on the order of open routines are not introduced by the programmer. Note that although an open can happen more than once, close is only called once. See the next section on the close routine for more details. If a file is duplicated (dup(2)) the stream is not reopened.

The prototype for the open entry point is:

int prefix_open(queue_t *q, dev_t *devp, int oflag, int sflag, 
						cred_t *cred_p)

Pointer to the read queue of this module.


Pointer to a device number that is always associated with the device at the end of the stream. Modules cannot modify this value, but drivers can, as described in Chapter 9, STREAMS Drivers.


For devices, oflag can contain the following bit mask values: FEXCL, FNDELAY, FREAD, and FWRITE. See Chapter 9, STREAMS Drivers for more information on drivers.


When the open is associated with a driver, sflag is set to 0 or CLONEOPEN, see Chapter 9, STREAMS Drivers, Cloning STREAMS Drivers for more details. If the open is associated with a module, sflag contains the value MODOPEN.


Pointer to the user credentials structure.

The open routines to devices are serialized . If more than one process attempts to open the device, only one proceeds and the others wait until the first finishes. Interrupts are not blocked during an open. The driver's interrupt routine must continue to handle interrupts when multiple processes are opening the same device. See Chapter 9, STREAMS Drivers for more information.

The open routines for both drivers and modules have user context. For example, they can do blocking operations, but the blocking routine should return in the event of a signal. In other words, q_wait_sig is allowed, but q_wait is not.

If the module or driver is to allocate a controlling terminal, it should send an M_SETOPTS message with SO_ISTTY set to the stream head.

The open routine usually initializes the q_ptr member of the queue. q_ptr is generally initialized to some private data structure that contains various state information private to the module or driver. The module's close routine is responsible for freeing resources allocated by the module including q_ptr. The following example shows a simple open routine.

Example 7–1 A Simple open Routine

/* example of a module open */
int xx_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
	struct xxstr *xx_ptr;

	xx_ptr = kmemzalloc(sizeof(struct xxstr), KM_SLEEP);
	xx_ptr->xx_foo = 1;
	q->q_ptr = WR(q)->q_ptr = xx_ptr;
	return (0);

In a multithreaded environment, data can flow up the stream during the open. A module receiving this data before its open routine finishes initialization can panic. To eliminate this problem, modules and drivers are not linked into the stream until qprocson(9F) is called (messages flow around the module). The following figure illustrates this process. See Chapter 12, Multithreaded STREAMS for more information on the multithreaded environment and the use of perimeters.

Figure 7–9 Messages Flowing Around the Module Before qprocson

Diagram shows how a module is linked after qprocon is called.

The module or driver instance is guaranteed to be single-threaded before qprocson(9F) is called, except for interrupts or callbacks that must be handled separately.

Note –

Hardening Information. qprocson must be called before calling qbufcall(9F), qtimeout(9F), qwait(9F), or qwait_sig(9F).

Before a module calls qprocson, it must be ready to accept data via the module's put procedure so all data structures must be fully initialized (see put Procedure). The most common method for calling qprocson is to call this function just before returning from a successful open (see Example 7–1).

Note –

For a multithreaded environment, verify you are using the correct perimeter before accessing data. See Chapter 12, Multithreaded STREAMS for more information on the multithreaded environment and the use of perimeters.