CLOSE(9E) | Driver Entry Points | CLOSE(9E) |
close - relinquish access to a device
#include <sys/types.h> #include <sys/file.h> #include <sys/errno.h> #include <sys/open.h> #include <sys/cred.h> #include <sys/ddi.h> #include <sys/sunddi.h> int prefixclose(dev_t dev, int flag, int otyp, cred_t *cred_p);
#include <sys/types.h> #include <sys/stream.h> #include <sys/file.h> #include <sys/errno.h> #include <sys/open.h> #include <sys/cred.h> #include <sys/ddi.h> #include <sys/sunddi.h> int prefixclose(queue_t *q, int flag, cred_t *cred_p);
Architecture independent level 1 (DDI/DKI). This entry point is required for block devices.
dev
flag
otyp
OTYP_BLK
OTYP_CHR
OTYP_LYR
*cred_p
*q
flag
*cred_p
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_EINTR cb_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:
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:
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.
If you use qwait_sig(9F), cv_wait_sig(9F) or cv_timedwait_sig(9F), you should note that close() may be called in contexts in which signals cannot be received. The ddi_can_receive_sig(9F) function is provided to determine when this hazard exists.
close(2), fcntl(2), open(2), umount(2), detach(9E), open(9E), ddi_can_receive_sig(9F), cb_ops(9S), qinit(9S), queue(9S)
Writing Device Drivers
STREAMS Programming Guide
April 24, 2008 | OmniOS |