Interface Level

Architecture independent level 1 (DDI/DKI). This entry point is required for block
devices.

Parameters

Block and Character

dev

Device number.

flag

File status flag, as set by the open(2) or modified by the fcntl(2) system calls. The flag is for information only—the file should always be closed completely. Possible values are: FEXCL, FNDELAY, FREAD,FKLYR, and FWRITE. Refer to open(9E) for more information.

otyp

Parameter supplied so that the driver can determine how many times a device was opened and for what reasons. The flags assume the open() routine may be called many times, but the close() routine should only be called on the last close() of a device.

OTYP_BLK

Close was through block interface for the device.

OTYP_CHR

Close was through the raw/character interface for the device.

OTYP_LYR

Close a layered process (a higher-level driver called the close() routine of the device).

*cred_p

Pointer to the user credential structure.

STREAMS

*q

Pointer to queue(9S) structure used to reference the read side of the driver. (A queue is the central node of a collection of structures and routines pointed to by a queue.)

flag

File status flag.

*cred_p

Pointer to the user credential structure.

Description

For STREAMS drivers, the close() routine is called by the kernel
through the cb_ops(9S) table entry for the device. (Modules use the
fmodsw table.) A non-null value in the d_str field of the
cb_ops entry points to a streamtab structure, which points to
a qinit(9S) containing a pointer to the close() routine. Non-STREAMS
close() routines are called directly from the cb_ops table.

close() ends the connection between the user process and the device, and
prepares the device (hardware and software) so that it is ready to
be opened again.

A device may be opened simultaneously by multiple processes and the open()
driver routine is called for each open. For all otyp values other
than OTYP_LYR, the kernel calls the close() routine when the last-reference occurs. For
OTYP_LYR each close operation will call the driver.

Kernel accounting for last-reference occurs at (dev, otyp) granularity. Note
that a device is referenced once its associated open(9E) routine is entered,
and thus open(9E)'s which have not yet completed will prevent close()
from being called. The driver's close() call associated with the
last-reference going away is typically issued as result of a close(2), exit(2),
munmap(2), or umount(2). However, a failed open(9E) call can cause this last-reference
close() call to be issued as a result of an open(2) or mount(2).

The kernel provides open()close() exclusion guarantees to the driver at the
same devp, otyp granularity as last-reference accounting. The kernel delays new calls
to the open() driver routine while the last-reference close() call is executing.
For example, a driver that blocks in close() will not see new
calls to open() until it returns from close(). This effectively
delays invocation of other cb_ops(9S) driver entry points that also depend on
an open(9E) established device reference. If the driver has indicated that an EINTR
return is safe via the D_OPEN_RETURNS_EINTRcb_flag, then a delayed open() may
be interrupted by a signal, resulting in an EINTR return from open()
prior to calling open(9E).

Last-reference accounting and open()close() exclusion typically simplify driver writing. In some
cases, however, they might be an impediment for certain types of drivers.
To overcome any impediment, the driver can change minor numbers in open(9E),
as described below, or implement multiple minor nodes for the same device.
Both techniques give the driver control over when close() calls occur and
whether additional open() calls will be delayed while close() is executing.

In general, a close() routine should always check the validity of
the minor number component of the dev parameter. The routine
should also check permissions as necessary, by using the user credential structure
(if pertinent), and the appropriateness of the flag and otyp parameter
values.

close() could perform any of the following general functions:

disable interrupts

hang up phone lines

rewind a tape

deallocate buffers from a private buffering scheme

unlock an unsharable device (that was locked in the open() routine)

flush buffers

notify a device of the close

deallocate any resources allocated on open

The close() routines of STREAMS drivers and modules are called when
a stream is dismantled or a module popped. The steps for dismantling
a stream are performed in the following order. First, any multiplexor links
present are unlinked and the lower streams are closed. Next, the following
steps are performed for each module or driver on the stream, starting
at the head and working toward the tail:

The write queue is given a chance to drain.

The close() routine is called.

The module or driver is removed from the stream.

Return Values

close() should return 0 for success, or the appropriate error number. Return
errors rarely occur, but if a failure is detected, the driver should
decide whether the severity of the problem warrants either displaying a message
on the console or, in worst cases, triggering a system panic. Generally,
a failure in a close() routine occurs because a problem occurred
in the associated device.