The following characteristics of kernel modules highlight important differences between the structure of kernel modules and the structure of user programs:
Kernel modules do not define a main program. Kernel modules, including device drivers, have no main() routine. Instead, a kernel module is a collection of subroutines and data. A device driver is a kernel module that forms a software interface to an input/output (I/O) device. The subroutines in a device driver provide entry points to the device. The kernel uses a device number attribute to locate the open() routine and other routines of the correct device driver. See Device Drivers for more information on entry points. See Device Numbers for a description of device numbers.
Kernel modules are linked only to the kernel. Kernel modules do not link in the same libraries that user programs link in. The only functions a kernel module can call are functions that are exported by the kernel. If your driver references symbols that are not defined in the kernel, your driver will compile but will fail to load. Solaris OS driver modules should use prescribed DDI/DKI (Device Driver Interface, Driver-Kernel Interface) interfaces. When you use these standard interfaces you can upgrade to a new Solaris release or migrate to a new platform without recompiling your driver. For more information on the DDI, seeDDI/DKI Interfaces in Writing Device Drivers. Kernel modules can depend on other kernel modules by using the -N option during link editing. See the ld(1) man page for more information.
Kernel modules use different header files. Kernel modules require a different set of header files than user programs require. The required header files are listed in the man page for each function. See man pages section 9: DDI and DKI Kernel Functions for DDI/DKI functions, man pages section 9: DDI and DKI Driver Entry Points for entry points, and man pages section 9: DDI and DKI Properties and Data Structures for structures. Kernel modules can include header files that are shared by user programs if the user and kernel interfaces within such shared header files are defined conditionally using the _KERNEL macro.
Kernel modules should avoid global variables. Avoiding global variables in kernel modules is even more important than avoiding global variables in user programs. As much as possible, declare symbols as static. When you must use global symbols, give them a prefix that is unique within the kernel. Using this prefix for private symbols within the module also is a good practice.
Kernel modules can be customized for hardware. Kernel modules can dedicate process registers to specific roles. Kernel code can be optimized for a specific processor.
Kernel modules can be dynamically loaded. The collection of subroutines and data that constitute a device driver can be compiled into a single loadable module of object code. This loadable module can then be statically or dynamically linked into the kernel and unlinked from the kernel. You can add functionality to the kernel while the system is up and running. You can test new versions of your driver without rebooting your system.