![]() |
![]() |
|||||||
4 Basic Kernel Driver Architecture4.1 Okay, I need to write a kernel mode driver. Tell me how.Too large a question for an FAQ, sorry. 4.2 What is the basic structure of a kernel mode driver?Every kernel mode driver must have a DriverEntry routine, and for all practical purposes, at least one Dispatch routine is required also. The DriverEntry routine must be called "DriverEntry", other routines can have any name you like. Drivers should also have an Unload routine, which permits the driver to be (guess what) unloaded, or removed from the system. 4.3 The NT driver doc talks about all these different types of drivers. How do they all relate to one another?4.3.1 Basic driver structureLet's define a "canonical" driver first. This will be a monolithic (non-layered) driver for a single-device controller that can handle only one I/O request at a time. In such a driver, I/O requests, which are described by data structures known as I/O Request Packets (IRPs), are handled by Dispatch, StartIo, InterruptService, and DpcForIsr routines, in that order. Unless the device is very well-behaved and can never interrupt unexpectedly, a SynchCritSection routine is also needed. If the device controller can be programmed for more than one I/O request at a time, the StartIo routine is usually replaced by one or more IrpQueueing routines. Any driver that holds I/O requests (ie that does not complete them right away or pass them on to other drivers) should have a Cancel routine. This includes any driver with a StartIo routine or an IrpQueueing routine. Drivers that use controller objects and/or adapter objects will usually have ControllerControl and/or AdapterControl routines, respectively. 4.3.2 What about layered drivers?NT allows drivers to be layered on top of one another. You can start with a monolithic (self-contained) driver and put an upper-layer driver above it. I/O requests to the device(s) controlled by the lower-layer driver now come to the upper-layer driver first. You can layer on top of any existing driver, but you cannot install a layer under a lowest-layer driver. The lowest-layer driver is the one that actually talks to the I/O hardware, and NT offers no mechanism for "hooking" or intercepting those operations and doing something else instead. Other driver layers are generically called "highest-layer" (the first driver that handles a particular IRP), "upper-layer" (any layer except the lowest), and "lower-layer" (any layer except the highest). In terms of routines, an upper-layer driver puts its own Dispatch routine(s) "ahead of" another driver's Dispatch routine(s). Hence, of all the routines in a driver that handle I/O, upper-layer drivers may often have only Dispatch routines. (They still have DriverEntry and Unload routines.) They may also have IoCompletion routines, which are invoked when the lower-layer driver completes an IRP that has come through the upper-layer driver. If an upper-layer driver does its own IRP queueing, it adds either StartIo or IrpQueueing routines, plus one or more Cancel routines. In that case, the flow of an I/O request is: Upper-layer driver, Dispatch and (StartIo or IrpQueueing), then lower-layer driver's Dispatch and subsequent routines. Upper-layer drivers do not handle interrupts, so they do not generally need an InterruptService routine, nor a DpcForIsr routine. They may have TimerDpc routines. A good "starter" example for an upper-layer driver is the DISKPERF driver. This driver collects disk I/O performance statistics and makes them available to Performance Monitor and related tools. NT driver layering is not at all like the Unix Streams environment. The NT driver layering mechanism is not completely generalized, and probably works best in environments where drivers at all layers are written by the same team, or at least by people who can speak with each other easily. It is not really possible or advisable to layer a driver on top of an existing driver unless you know quite a bit about how the driver you're on top of does things. For example, drivers that use buffered I/O are usually incompatible with the associated IRP mechanism. How do you know if your soon-to-be-lower-layer driver uses buffered I/O? You just have to attach to its device object and look. For that matter, the associated IRP mechanism is incompatible with itself; only one driver in a stack of layered drivers can safely IoMakeAssociatedIrp. 4.3.3 What about file system drivers?A file system driver is generally a highest-layer driver sitting atop the driver for random-access mass storage devices. It implements the semantics of file-system-oriented I/O requests, such as requests to create, open, extend, and delete files and directories. Different file system drivers exist for different on-disk structures, such as FAT, NTFS, and the CD-ROM file system. File system drivers are presently difficult to write, conceptually because they have complex jobs to do and have intricate interactions with the cache and the memory manager, and practically because Microsoft has not put much information about them in the DDK documentation, and some necessary header files and libraries are missing from the DDK. Microsoft offers a separate Installable File System Kit that installs "on top of" the DDK and provides source for some example file system drivers. Open Systems Resources (see the Products links page) has a File System Developers Kit with more documentation, more examples, and ongoing support. 4.3.4 What are class and port drivers?Class and port drivers exist for I/O hardware in which a number of substantially different types, or classes, of I/O devices are accessed through a common I/O device controller. The class drivers implement the semantics of the different types of devices, such as disks vs. tapes, while the port driver deals with programming the controller's I/O ports (hence "port driver") or registers. 4.3.5 What about NIC miniport drivers?A NIC miniport driver is a lowest-layer driver which is "wrapped" by support routines provided by the NDIS port driver. It provides support for a specific network interface card (NIC). 4.3.6 What about SCSI miniport drivers?An SCSI miniport driver is a lowest-layer driver which is "wrapped" by support routines provided by the SCSI port driver. It provides support for a specific SCSI controller. 4.3.7 What is this port/miniport thing?Microsoft realized that all SCSI port drivers would have a great deal of common code, because they would all have to interface with the existing SCSI class drivers. Similarly, all NIC drivers would have a great deal of common code, because they would all have to interface with the existing transport-layer drivers. The SCSI port driver and NDIS port driver, respectively, attempt to pull all of this common code into common modules within NT. The port drivers also abstract the NT I/O support routines. For example, a NIC miniport driver does not call IoMapTransfer, but rather NdisMSetupDmaTransfer. They do this to such an extent that other operating systems, such as Windows 95, can supply a NDIS port driver and SCSI port driver and hence allow the miniport drivers to be compatible with those other systems. top of page | up | previous | next | home |
||||||||