Loading and Unloading Kernel Extensions
Kernel extensions can be loaded and unloaded by calling the sysconfig function from user applications. A
kernel extension can load another kernel extension by using the kmod_load kernel service, and kernel
extensions can be unloaded by using the kmod_unload kernel service.
Loading Kernel Extensions: Normally, kernel extensions that provide new system calls or kernel
services only need to be loaded once. For these kernel extensions, loading should be performed by
specifying SYS_SINGLELOAD when calling the sysconfig function, or LD_SINGLELOAD when calling the
kmod_load function. If the specified kernel extension is already loaded, a second copy is not loaded.
Instead, a reference to the existing kernel extension is returned. The loader uses the specified pathname
to determine whether a kernel extensions is already loaded. If multiple pathnames refer to the same kernel
extension, multiple copies can be loaded into the kernel.
If a kernel extension can support multiple instances of itself (particularly its data), it can be loaded multiple
times, by specifying SYS_KLOAD when calling the sysconfig function, or by not specifying
LD_SINGLELOAD when calling the kmod_load function. Either of these operations loads a new copy of
the kernel extension, even when one or more copies are already loaded. When this operation is used,
currently loaded routines bound to the old copy of the kernel extension continue to use the old copy.
Subsequently loaded routines use the most recently loaded copy of the kernel extension.
Unloading Kernel Extensions: Kernel extensions can be unloaded. For each kernel extension, the
loader maintains a use count and a load count. The use count indicates how many other object files have
referenced some exported symbol provided by the kernel extension. The load count indicates how many
explicit load requests have been made for each kernel extension.
When an explicit unload of a kernel extension is requested, the load count is decremented. If the load
count and the use count are both equal to 0, the kernel extension is unloaded, and the memory used by
the text and data of the kernel extension is freed.
If either the load count or use count is not equal to 0, the kernel extension is not unloaded. As processes
exit or other kernel extensions are unloaded, the use counts for referenced kernel extensions are
decremented. Even if the load and use counts become 0, the kernel extension may not be unloaded
immediately. In this case, the kernel extension’s exported symbols are still available for load-time binding
unless another kernel extension is unloaded or the slibclean command is executed. At this time, the
loader unloads all modules that have both load and use counts of 0.
Using Private Routines
So far, symbol resolution for kernel extensions has been concerned with importing and exporting symbols
from and to the kernel name space. Exported symbols are global in the kernel, and can be referenced by
any subsequently loaded kernel extension.
Kernel extensions can also consist of several separately link-edited modules. This is particularly useful for
device drivers, where a kernel extension contains the top (pageable) half of the driver and a dependent
module contains the bottom (pinned) half of the driver. Using a dependent module also makes sense when
several kernel extensions use common routines. In both cases, the symbols exported by the dependent
modules are not added to the global kernel name space. Instead, these symbols are only available to the
kernel extension being loaded.
When link-editing a kernel extension that depends on another module, an import file should be specified
listing the symbols exported by the dependent module. Before any symbols are listed, the import file
should contain one of the following lines:
#! path/file
or
#! path/file(member)
Chapter 1. Kernel Environment 3