libdevinfo Userland Access to Solaris Device Information
Programming Model
Taking a SnapshotThe kernel device tree is a dynamic entity. Device nodes might come and go as a result of driver module loading/unloading and user-initiated device reconfiguration. To obtain a consistent view of the device tree, libdevinfo locks the kernel device tree, takes a snapshot, and passes the snapshot data to user applications. Using HandlesApplications access snapshot data through a set of opaque handles:
These handles are to be used as arguments to libdevinfo interfaces only; applications should not manipulate them directly. Note that properties defined in the PROM differ from other properties in that PROM properties persist across reboots. Using libdevinfoTo use libdevinfo, follow these steps, which are described in detail in the sections below:
Create a Snapshot of the Device TreeA snapshot of the device tree is created by calling di_init(3). The statement:
creates a snapshot of the device tree, which includes all information accessible through libdevinfo, which is not necessarily the same as what /devices exposes. The return value of di_init() is a handle to the root device node; using the handle, the application can access the information in the snapshot. Control over what information to include in the snapshot is provided by the second argument to the function di_init(), which is a bitwise OR of the following fields:
At minimum, applications can snapshot a single node with its attributes by specifying a physical path as the first argument and 0 as the second argument to di_init(). Applications can specify DINFOPROP, DINFOMINOR, DINFOSUBTREE, or a combination OR'ed together in the second argument. Specifying DINFOPROP will include properties; DINFOMINOR, minor node data; and DINFOSUBTREE, device nodes in the subtree rooted at the node specified by the first argument. DINFOCPYALL is defined for convenience; it is a bitwise OR of all three flags. The physical path is a name space private to the Solaris DDI. Given a handle to a device node, the physical path can be obtained by calling di_devfs_path(3). The physical path to the root of the device tree is "/". Traverse the Device Tree SnapshotThe device tree can be traversed through parent, child, and sibling linkage. Each device node contains references to its parent, its next sibling, and its first child. Given the root node handle returned from di_init(), applications can locate the root node's children by first calling di_child_node(3), and subsequently calling di_sibling_node(3), until DI_NODE_NIL is returned. By following this procedure recursively, applications can visit all device nodes contained in the snapshot. As an alternative to this, traversing the entire device tree is simplified by calling di_walk_node(3), which visits all device nodes in a snapshot and executes a caller-supplied function for each device node. The caller can specify depth-first or breadth-first walking order. The device tree can also be traversed through per-driver linkage, which is an association of all nodes bound to the same device driver. This is done by calling di_drv_first_node(3), followed by successive calls to di_drv_next_node(3) until DI_NODE_NIL is returned. Note that traversing the per-driver device node list is allowed only when the snapshot includes all device nodes. If the snapshot does not contain all device nodes, the node selection can only be done by checking the driver name of every device node in the tree. Access Device Node InformationThere are three types of device node information:
Destroy the SnapshotA snapshot is destroyed by calling: di_fini(root); where root is the handle returned from di_init(). Destroying a snapshot has the effect of freeing all memory associated with that snapshot and invalidating all associated handles. The application must ensure that invalidated handles are not referenced. Header File and CompilationSource files should include the libdevinfo.h header file:#include <libdevinfo.h> The application should be linked with libdevinfo using the -ldevinfo option: cc program.c ... -ldevinfo 64-bit ImplicationsThe 32-bit version of libdevinfo works on top of both the 64-bit and 32-bit Solaris kernels. This means that most device administration programs do not require conversion or recompilation to work with the 64-bit kernel. The only caveat is that when the representation of device number (dev_t) grows from 32-bit to 64-bit in the 64-bit kernel, the 32-bit libdevinfo will represent large device numbers (a major number greater than 14 bits or minor number greater than 18 bits) as NODEV. The relevant interfaces are di_prop_devt(3), di_minor_devt(3), and property lookup functions. A 64-bit version of libdevinfo is also available for 64-bit applications. Memory ManagementThe libdevinfo interfaces handle memory allocation and deallocation internally. The user must call the following interfaces in pairs to avoid memory leaks:
Error InformationThe libdevinfo interfaces indicate error conditions by setting the errno variable. Mapping of error codes to error conditions are described in the man pages. No error strings are passed to the caller or directed to any output. Here are the most common error codes:
InternationalizationThe libdevinfo interfaces do not output any strings. These functions can be used by internationalized applications with no special modifications. LimitationsThe libdevinfo interfaces do not permit modification of device configuration data, and they do not provide the capability to track changes in the device configuration data. These limitations are by design to make the interfaces user-friendly.
| ||||||||||||||||||||||||||||||||||||||||||||||||||
|
| ||||||||||||